<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="React、JSX 表达式、组件开发、路由功能、状态管理库">
<meta property="og:type" content="article">
<meta property="og:title" content="React 框架">
<meta property="og:url" content="https://chuangges.gitee.io/2019/08/17/10-1-React%E6%A1%86%E6%9E%B6/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="React、JSX 表达式、组件开发、路由功能、状态管理库">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://chuangges.gitee.io/images/frame/jsx.png">
<meta property="og:image" content="https://chuangges.gitee.io/images/frame/life_cycle.png">
<meta property="article:published_time" content="2019-08-17T14:05:46.000Z">
<meta property="article:modified_time" content="2023-12-01T11:07:05.144Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="JS 框架">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://chuangges.gitee.io/images/frame/jsx.png">

<link rel="canonical" href="https://chuangges.gitee.io/2019/08/17/10-1-React%E6%A1%86%E6%9E%B6/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>React 框架 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2019/08/17/10-1-React%E6%A1%86%E6%9E%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          React 框架
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-08-17 22:05:46" itemprop="dateCreated datePublished" datetime="2019-08-17T22:05:46+08:00">2019-08-17</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-12-01 19:07:05" itemprop="dateModified" datetime="2023-12-01T19:07:05+08:00">2023-12-01</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JS-%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">JS 框架</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>48k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>44 分钟</span>
            </span>
            <div class="post-description">React、JSX 表达式、组件开发、路由功能、状态管理库</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、开发技术"><a href="#一、开发技术" class="headerlink" title="一、开发技术"></a>一、开发技术</h1><ul>
<li><strong>脚手架</strong>：<code>create-react-app</code> 官方推荐、<code>Vite</code> 构建工具、<code>Umi Ice</code> 蚂蚁和阿里的前端框架、<code>nwb</code> 构建应用和库的工具包、<code>Neutrino</code> 构建初始配置的应用、<code>NextJS</code> 构建基于 NodeJS 的服务端应用、<code>Razzle</code> 构建无配置的服务端应用、<code>Gatsby</code> 构建静态网站。</li>
<li><strong>底层框架</strong>：<code>Umi Ice</code> 前端应用框架、<code>NextJS Razzle</code> 服务端渲染(后者无需配置)、<code>Remix</code> 全栈开发、<code>Flutter ReactNative Ionic Taro</code> 跨平台开发、<code>Gatsby</code> 静态网站部署。</li>
<li><strong>UI 组件库</strong>：<code>Ant-design</code> 阿里、<code>Arco-design</code> 字节、<code>TDesign</code> 腾讯、<code>MaterialUI MUI</code> 谷歌、<code>Zarm</code> 众安、<code>NutUI</code> 京东、<code>WeUI</code> 微信、<code>Chakra</code> 响应式、<code>Blueprint</code> 桌面应用。</li>
<li><strong>单页面开发</strong>：<code>create-react-app umi</code> 初始化结构，<code>Component</code> 开发组件、<code>JSX</code> 扩展语法、<code>react-router</code> 管理路由、<code>storybook</code> 组件测试、<code>react-devtools</code> 项目调试。</li>
<li><strong>样式策略</strong>：<code>JSX</code> 内联、<code>CSS SCSS</code> 文件、<code>styled-components Jss Radium</code> 使用 JS。</li>
<li><strong>状态管理</strong>：<code>Redux Zustand</code> 手动更新的单向数据流、<code>Mobx Valtio</code> 响应式自动更新的双向绑定、<code>Jotai Recoil</code> 多组件数据共享的状态原子化、<code>Xsate</code> 管理复杂状态跳转的有限状态机、<code>Rxjs</code> 自定义数据流的异步编程库、<code>Dva</code> 基于 redux + react-router + redux-saga 进行二次封装的数据流方案、<code>React-Query + Context</code> 分别管理服务端和客户端的状态。</li>
<li><strong>技术展望</strong>：<code>pnpm</code> 更快更节省空间的包管理工具 (取代 npm)、<code>Vite</code> 按需编译的构建工具 (取代 webpack)、<code>Tailwindcss</code> 构建定制化样式的框架 (取代 CSS 及其预处理工具)，<code>React-Query</code> 服务端异步状态管理器 (取代异步请求时需要维护大量状态的 Redux&#x2F;MobX)。</li>
</ul>
<h2 id="React-简介"><a href="#React-简介" class="headerlink" title="React 简介"></a>React 简介</h2><blockquote>
<p>Facebook 开源的一个用于动态构建界面的视图框架。它采用声明范式来描述应用，构建虚拟 DOM，支持 JSX 语法，通过 React.Component 构建可复用组件，通过 props 实现简单的父子组件通信，它并不是复杂应用的完整解决方案，还需要集成 react-router、react-redux、redux-saga、Ant-design 等第三方库或者直接使用一个应用级框架。</p>
</blockquote>
<ol>
<li><strong>声明式设计</strong>：采用简洁易懂的声明范式，可以轻松描述应用。</li>
<li><strong>单向数据流</strong>：推崇一种单向的数据流动模式，减少了重复代码。</li>
<li><strong>高效渲染</strong>：通过组件构建 <code>Virtual DOM</code> (描述元素的对象)，更新时通过算法 <code>react-diff</code> 只将差异部分重新渲染到真实元素，相比每次遍历元素属性的传统方式而极大提升了性能。</li>
<li><strong>组件化开发</strong>：DOM 树上的节点称为<code>元素</code>，Virtual DOM 上的节点则称为<code>组件</code>。组件具有功能独立、高内聚、低耦合的特点，开发时不能用模板而推荐使用 <code>JSX</code>。</li>
<li><strong>支持客户端与服务器渲染</strong>：服务端渲染 (Node)、APP (ReactNative)。</li>
</ol>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 虚拟 DOM</span></span><br><span class="line"><span class="keyword">const</span> span = <span class="title class_">React</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;span&#x27;</span>, <span class="literal">null</span>, <span class="string">&#x27;玫瑰&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> p = <span class="title class_">React</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;p&#x27;</span>, &#123; <span class="attr">className</span>: <span class="string">&#x27;active&#x27;</span>&#125;, <span class="string">&#x27;花&#x27;</span>, span)</span><br><span class="line"><span class="title class_">ReactDOM</span>.<span class="title function_">render</span>(p, <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;app&#x27;</span>))</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> list = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;4&#x27;</span>];</span><br><span class="line"><span class="title class_">ReactDOM</span>.<span class="title function_">render</span>(</span><br><span class="line">    <span class="string">`&lt;ul&gt;&#123;list.map((item,index) =&gt; &lt;li key=&#123;index&#125;&gt;&#123;item&#125;&lt;/li&gt;)&#125;&lt;/ul&gt;`</span>, </span><br><span class="line">    <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;app&#x27;</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 命令式编程</span></span><br><span class="line"><span class="keyword">const</span> map = <span class="keyword">new</span> <span class="title class_">Map</span>.<span class="title function_">map</span>(<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;m&#x27;</span>), &#123;<span class="attr">center</span>: &#123;lat,lng&#125;&#125;)</span><br><span class="line"><span class="keyword">const</span> marker = <span class="keyword">new</span> <span class="title class_">Map</span>.<span class="title function_">marker</span>(&#123; <span class="attr">position</span>: &#123;lat, lng&#125;, <span class="attr">title</span>: <span class="string">&#x27;Marker&#x27;</span> &#125;)</span><br><span class="line">marker.<span class="title function_">setMap</span>(map)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明式编程</span></span><br><span class="line">&lt;<span class="title class_">Map</span> zoom=&#123;<span class="number">4</span>&#125; center=&#123;lat, lng&#125;&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">Marker</span> <span class="attr">position</span>=<span class="string">&#123;lat,</span> <span class="attr">lng</span>&#125; <span class="attr">title</span>=<span class="string">&#123;</span>&#x27;<span class="attr">Hello</span> <span class="attr">Marker</span>&#x27;&#125;/&gt;</span></span></span><br><span class="line">&lt;/<span class="title class_">Map</span>&gt;</span><br></pre></td></tr></table></figure>


<h2 id="项目构建"><a href="#项目构建" class="headerlink" title="项目构建"></a>项目构建</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// create-react-app：基于 webpack 大而全的打包层方案</span></span><br><span class="line">npx create-react-app react-app</span><br><span class="line">npm start        <span class="comment">// 开发模式运行</span></span><br><span class="line">npm run build    <span class="comment">// 生产模式打包</span></span><br><span class="line">npm test         <span class="comment">// 测试模式测试</span></span><br><span class="line">npm run eject    <span class="comment">// 显示配置文件 webpack.config.js</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Vite：小而巧的打包层方案</span></span><br><span class="line">npm install vite -g</span><br><span class="line">npm init vite-app --template react</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Umi4：整合了 React 生态的应用框架，推荐高性能 npm 的 pnpm </span></span><br><span class="line">npm i pnpm -g</span><br><span class="line">pnpm config set registry <span class="attr">https</span>:<span class="comment">//registry.npmmirror.com</span></span><br><span class="line">pnpm dlx create-umi@latest</span><br><span class="line">npx create-umi@latest</span><br><span class="line">pnpm run dev、npm start</span><br><span class="line"></span><br><span class="line"><span class="comment">// Umi3：注意不要混淆新版命令</span></span><br><span class="line">npx @umijs/create-umi-app</span><br><span class="line">npm create @umijs/umi-app</span><br><span class="line">npm start</span><br></pre></td></tr></table></figure>


<h2 id="样式策略"><a href="#样式策略" class="headerlink" title="样式策略"></a>样式策略</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 内联样式</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Button</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> buttonGreen = &#123;</span><br><span class="line">        <span class="attr">backgroundColor</span>: <span class="string">&quot;green&quot;</span>,</span><br><span class="line">        <span class="attr">border</span>: <span class="string">&quot;1px solid white&quot;</span>,</span><br><span class="line">        <span class="attr">borderRadius</span>: <span class="string">&quot;2px&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span>(<span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">style</span>=<span class="string">&#123;buttonGreen&#125;</span>&gt;</span>green<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 样式文件</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">TestChidren</span> <span class="keyword">from</span> <span class="string">&quot;./TestChidren&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;@/assets/css/index.scss&quot;</span>;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props, context</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;link-name&quot;</span>&gt;</span>123<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">TestChidren</span>&gt;</span>子组件样式<span class="tag">&lt;/<span class="name">TestChidren</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">Test</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm i react-jss -D：支持复用、局部、props 动态样式</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123;createUseStyles&#125; <span class="keyword">from</span> <span class="string">&#x27;react-jss&#x27;</span></span><br><span class="line"><span class="keyword">const</span> useStyles = <span class="title function_">createUseStyles</span>(&#123;</span><br><span class="line">    <span class="attr">buttonGreen</span>: &#123;</span><br><span class="line">        <span class="attr">backgroundColor</span>: <span class="function"><span class="params">backgroundColour</span> =&gt;</span> backgroundColour,</span><br><span class="line">        <span class="attr">border</span>: <span class="string">&quot;1px solid white&quot;</span>,</span><br><span class="line">        <span class="attr">borderRadius</span>: <span class="string">&quot;2px&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Button</span> = (<span class="params">&#123;backgroundColour, children&#125;</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123;buttonStyles&#125; = <span class="title function_">useStyles</span>(backgroundColour)</span><br><span class="line">    <span class="keyword">return</span>(</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">className</span>=<span class="string">&#123;buttonStyles&#125;</span>&gt;</span>&#123;children&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm i styled-components -D：支持 Sass、props 动态样式</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> styled <span class="keyword">from</span> <span class="string">&quot;styled-components&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Btn</span> = styled.<span class="property">button</span><span class="string">`background: blue;`</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">CoolButton</span> = <span class="title function_">styled</span>(<span class="title class_">Btn</span>)<span class="string">`color: pink;`</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Title</span> = styled.<span class="property">div</span><span class="string">`</span></span><br><span class="line"><span class="string">    text-align: center;</span></span><br><span class="line"><span class="string">    img &#123;</span></span><br><span class="line"><span class="string">        height: 100px;</span></span><br><span class="line"><span class="string">        width: 200px;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    p &#123;</span></span><br><span class="line"><span class="string">        font-size: 20px;</span></span><br><span class="line"><span class="string">        color: <span class="subst">$&#123;props =&gt; props.color&#125;</span>;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">`</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params">&#123;imgUrl, themeColor&#125;</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">Title</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">p</span> <span class="attr">color</span>=<span class="string">&#123;themeColor&#125;</span>&gt;</span>Hello World<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#123;imgURl&#125;</span> <span class="attr">alt</span>=<span class="string">&quot;&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">Title</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm i radium -D：扩展内联样式，支持变量、伪类、媒体查询、动画</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Radium</span> <span class="keyword">from</span> <span class="string">&#x27;radium&#x27;</span>;</span><br><span class="line"><span class="keyword">let</span> styles = &#123;</span><br><span class="line">    <span class="attr">base</span>: &#123;</span><br><span class="line">        <span class="attr">color</span>: <span class="string">&#x27;#fff&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;:hover&#x27;</span>: &#123;</span><br><span class="line">            <span class="attr">background</span>: <span class="string">&#x27;#0074d9&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">primary</span>: &#123;</span><br><span class="line">        <span class="attr">background</span>: <span class="string">&#x27;#0074D9&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">warning</span>: &#123;</span><br><span class="line">        <span class="attr">background</span>: <span class="string">&#x27;#FF4136&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props, context</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props);</span><br><span class="line">    &#125; </span><br><span class="line">    </span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">style</span>=<span class="string">&#123;[styles.base,</span> <span class="attr">styles.primary</span>]&#125;&gt;</span>P<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="JSX-语法"><a href="#JSX-语法" class="headerlink" title="JSX 语法"></a>JSX 语法</h2><blockquote>
<p>Facebook 提出的 <code>JS 扩展语法、React.Fragment 语法糖</code>，主要用于创建虚拟 DOM 并被 babel 编译为 React.createElement。主要优点有编写组件简单、渲染时输出虚拟 dom 提高性能、渲染前将传入值转为字符串而防止 XSS 跨站脚本攻击，实现原理和使用规则如下：</p>
</blockquote>
  <div align="center">
      <img src="" data-original="/images/frame/jsx.png" alt="JSX 原理" width="100%">
  </div>

<ul>
<li>表格标签必须添加 tbody。</li>
<li>最外层有且只有一个标签，但可以是空标签。</li>
<li>对大小写敏感，区分是组件还是 html 标签。</li>
<li>所有的标签必须闭合，单标签必须有末尾反斜杠。</li>
<li>标签内放 <code>&lt;</code> 会报错，因为他会按照 html 来解析。</li>
<li>在标签内部的注释需要写入 <code>&#123;&#125;</code>，在标签外的的注释则不需要。</li>
<li><code>&#123;&#125;</code> 不可插入：函数声明、对象、for 循环、if 语句、while 语句。</li>
<li><code>&#123;&#125;</code> 可插入：变量、简单运算、JS 内置函数、函数执行、三元运算符、自定义组件。</li>
<li>属性名：小驼峰命名，不能使用关键字：<code>class - classNmae、for - htmlFor</code>。</li>
<li>属性值：字符串加引号，变量加 <code>&#123;&#125;</code>。有换行符时设置样式 <code>whiteSpace: &#39;pre-wrap&#39;</code>。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 解析规则：&lt; 开头的标签使用 HTML 规则解析、&#123; 开头的使用 JS 规则解析</span></span><br><span class="line"><span class="comment">// 编译前：JSX 表达式</span></span><br><span class="line">&lt;div <span class="keyword">class</span>=<span class="string">&quot;input-wrap&quot;</span>&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">value</span>=<span class="string">&quot;&quot;</span> <span class="attr">class</span>=<span class="string">&quot;input&quot;</span> <span class="attr">title</span>=<span class="string">&quot;请输入&quot;</span> /&gt;</span></span></span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">button</span>&gt;</span>搜索<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">&lt;/div&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 编译过程：执行 React.createElement</span></span><br><span class="line"><span class="title class_">React</span>.<span class="title function_">createElement</span>(<span class="string">&quot;div&quot;</span>, &#123;<span class="attr">className</span>: <span class="string">&#x27;input-wrap&#x27;</span>&#125;,</span><br><span class="line">    <span class="title class_">React</span>.<span class="title function_">createElement</span>(</span><br><span class="line">        <span class="string">&quot;input&quot;</span>,</span><br><span class="line">        &#123; <span class="attr">type</span>: <span class="string">&#x27;text&#x27;</span>, <span class="attr">value</span>: <span class="string">&#x27;&#x27;</span>, <span class="attr">class</span>: <span class="string">&#x27;input&#x27;</span>, <span class="attr">title</span>: <span class="string">&#x27;请输入&#x27;</span> &#125;</span><br><span class="line">    ),</span><br><span class="line">    <span class="title class_">React</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;button&#x27;</span>, <span class="literal">null</span>, <span class="string">&quot;搜索&quot;</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 编译结果：虚拟 DOM</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="attr">tagName</span>: <span class="string">&#x27;div&#x27;</span>,</span><br><span class="line">  <span class="attr">attribute</span>: &#123; <span class="attr">className</span>: <span class="string">&#x27;input-wrap&#x27;</span>&#125;,</span><br><span class="line">  <span class="attr">children</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">tagName</span>: <span class="string">&#x27;input&#x27;</span>,</span><br><span class="line">      <span class="attr">attribute</span>: &#123; <span class="attr">type</span>: <span class="string">&#x27;text&#x27;</span>, <span class="attr">value</span>:<span class="string">&#x27;&#x27;</span>, <span class="attr">class</span>:<span class="string">&#x27;input&#x27;</span>, <span class="attr">title</span>:<span class="string">&#x27;请输入&#x27;</span> &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123; <span class="attr">tagName</span>: <span class="string">&quot;button&quot;</span>, <span class="attr">attribute</span>: <span class="literal">null</span>, <span class="attr">children</span>: <span class="string">&#x27;搜索&#x27;</span> &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">============= 基础使用 =============</span><br><span class="line"><span class="comment">// 空标签：&lt;React.Fragment /&gt; 的语法糖</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Columns</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;&gt;</span><span class="tag">&lt;<span class="name">td</span>&gt;</span>Hello<span class="tag">&lt;/<span class="name">td</span>&gt;</span><span class="tag">&lt;/&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 属性值</span></span><br><span class="line">&lt;div tabIndex=<span class="string">&quot;0&quot;</span>&gt;&lt;/div&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span> = <span class="string">&#123;</span>`<span class="attr">images</span>/$&#123;<span class="attr">star</span>&#125;<span class="attr">.png</span>`&#125; /&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">span</span> <span class="attr">className</span>=<span class="string">&#123;</span>`<span class="attr">tab</span> $&#123;<span class="attr">index</span>==<span class="string">this.state.i</span> ? &#x27;<span class="attr">active</span>&#x27;<span class="attr">:</span>&#x27;&#x27;&#125;`&#125;&gt;</span>标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="keyword">const</span> props = &#123; <span class="attr">name</span>: <span class="string">&quot;Jack&quot;</span>, <span class="attr">age</span>: <span class="number">20</span>, <span class="attr">children</span>: [] &#125;</span><br><span class="line">&lt;span &#123;...props&#125;&gt;&lt;/span&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 行内样式：双大括号，标准 JSON，省略 px，名字性驼峰</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">style</span>=<span class="string">&#123;&#123;width:</span> <span class="attr">200</span>, <span class="attr">height:</span> <span class="attr">200</span>, <span class="attr">backgroundColor</span> <span class="attr">:</span> &#x27;<span class="attr">red</span>&#x27;&#125;&#125;&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">style</span>=<span class="string">&#123;&#123;display:</span> (<span class="attr">index</span>==<span class="string">this.state.i)</span> ? &#x27;<span class="attr">block</span>&#x27; <span class="attr">:</span> &#x27;<span class="attr">none</span>&#x27;&#125;&#125;&gt;</span>标签<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 条件渲染</span></span><br><span class="line"><span class="keyword">const</span> isBtn = <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">isBtn</span></span><br><span class="line">&lt;div&gt;&#123; isBtn &amp;&amp; <span class="language-xml"><span class="tag">&lt;<span class="name">Button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.handleClick&#125;</span> /&gt;</span></span>&#125;&lt;/div&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123; isBtn ? <span class="tag">&lt;<span class="name">Button</span> /&gt;</span> : <span class="tag">&lt;<span class="name">span</span>&gt;</span>内容<span class="tag">&lt;/<span class="name">span</span>&gt;</span> &#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="keyword">if</span> (isBtn) &#123; <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">Button</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span> &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Render</span> (&#123; <span class="attr">if</span>: cond, children &#125;) &#123;</span><br><span class="line">    <span class="keyword">return</span> cond ? children : <span class="literal">null</span></span><br><span class="line">&#125;</span><br><span class="line">&lt;<span class="title class_">Render</span> <span class="keyword">if</span>=&#123;status === <span class="string">&#x27;loading&#x27;</span>&#125; &gt;加载&lt;/<span class="title class_">Render</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 表达式</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">formatName</span>(<span class="params">user</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;user.firstName&#125;</span> <span class="subst">$&#123;user.lastName&#125;</span>`</span>;</span><br><span class="line">&#125;</span><br><span class="line">render () &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;wrap&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>&#123;parseInt(Math.random() * 100)&#125;年<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h2</span>&gt;</span>&#123;formatName(this.state.user)&#125;<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 列表</span></span><br><span class="line">&lt;ul&gt;&#123;arr.<span class="title function_">map</span>(<span class="function">(<span class="params">item,index</span>)=&gt;</span> <span class="language-xml"><span class="tag">&lt;<span class="name">li</span> <span class="attr">key</span>=<span class="string">&#123;index&#125;</span>&gt;</span> &#123;item&#125; <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span>)&#125;&lt;/ul&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 事件</span></span><br><span class="line"><span class="keyword">import</span> cn <span class="keyword">from</span> <span class="string">&#x27;classnames&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">CustomIcon</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; type, className, active=<span class="literal">false</span>, onClick &#125; = props;</span><br><span class="line">    <span class="keyword">const</span> cls = <span class="title function_">cn</span>(<span class="string">&#x27;custom-icon&#x27;</span>, className, <span class="string">`custom-icon**<span class="subst">$&#123;type&#125;</span>`</span>, &#123;</span><br><span class="line">        <span class="string">&#x27;custom-icon--active&#x27;</span>: active</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">i</span> <span class="attr">className</span>=<span class="string">&#123;cls&#125;</span> <span class="attr">onClick</span>=<span class="string">&#123;onClick&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">CustomIcon</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@C/_common&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">DeletableBlock</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; title, children, index, onDelete &#125; = props;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&#x27;cc-delete-block&#x27;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">          <span class="tag">&lt;<span class="name">CustomIcon</span> <span class="attr">type</span>=<span class="string">&quot;delete&quot;</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>handleDelete(index)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">          &#123;/* 注释：子组件 */&#125;</span></span><br><span class="line"><span class="language-xml">          &#123;children&#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">handleDelete</span>(<span class="params">index</span>) &#123;</span><br><span class="line">        <span class="title function_">onDelete</span>(index)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="Vite-工具"><a href="#Vite-工具" class="headerlink" title="Vite 工具"></a>Vite 工具</h2><blockquote>
<p>一个基于浏览器原生 ES imports 的开发服务器。主要原理是服务器拦截浏览器发出的 ES imports 请求并做相应处理后返回，整个过程没有对文件进行打包编译，所以热更新的速度不会随着模块增多而变慢，但是 Vite 处理的是开发模式而在生产模式则可以通过 rollup 打包。主要优点有快速冷启动服务器、即时热模块更换 HMR、真正的按需编译。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Vite 搭建项目</span></span><br><span class="line">npm install vite -g</span><br><span class="line">npm init vite-app --template react</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 实现原理</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@desp</span>  1、模块引入路径按需修改：import &#123; createApp &#125; from &#x27;<span class="doctag">@modules</span>/vue.js&#x27;</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@desp</span>  2、浏览器发起请求：GET localhost:3000/src/main.js、/<span class="doctag">@modules</span>/vue.js</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@desp</span>  3、Vite 劫持包含浏览器请求并通过服务器解析处理后返回，</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line"><span class="comment">// main.js</span></span><br><span class="line"><span class="keyword">import</span> &#123; createApp &#125; <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&#x27;./App.vue&#x27;</span></span><br><span class="line"><span class="title function_">createApp</span>(<span class="title class_">App</span>).<span class="title function_">mount</span>(<span class="string">&#x27;#app&#x27;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// vite/index.js：简单实现</span></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>).<span class="property">promises</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Koa</span> = <span class="built_in">require</span>(<span class="string">&#x27;koa&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> chalk = <span class="built_in">require</span>(<span class="string">&#x27;chalk&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> <span class="keyword">static</span> = <span class="built_in">require</span>(<span class="string">&#x27;koa-static&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> &#123; parse &#125; = <span class="built_in">require</span>(<span class="string">&#x27;es-module-lexer&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">MagicString</span> = <span class="built_in">require</span>(<span class="string">&#x27;magic-string&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> &#123; <span class="title class_">Readable</span> &#125; = <span class="built_in">require</span>(<span class="string">&#x27;stream&#x27;</span>)</span><br><span class="line"><span class="comment">// 读取 body 方法</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">readBody</span>(<span class="params">stream</span>) &#123;    </span><br><span class="line">    <span class="keyword">if</span> (stream <span class="keyword">instanceof</span> <span class="title class_">Readable</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">let</span> res = <span class="string">&#x27;&#x27;</span></span><br><span class="line">            stream.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="keyword">function</span> (<span class="params">chunk</span>) &#123;</span><br><span class="line">                res += chunk</span><br><span class="line">            &#125;)</span><br><span class="line">            stream.<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">                <span class="title function_">resolve</span>(res)</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> stream;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// koa 中间件</span></span><br><span class="line"><span class="keyword">const</span> resolvePlugin = [  </span><br><span class="line">    <span class="comment">// 1、模块引入路径前面加 /@modules/vue，重写后浏览器会再次发送请求</span></span><br><span class="line">    <span class="function">(<span class="params">&#123; app, root &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">rewriteImports</span>(<span class="params">source</span>) &#123;</span><br><span class="line">            <span class="keyword">let</span> imports = <span class="title function_">parse</span>(source)[<span class="number">0</span>];</span><br><span class="line">            <span class="keyword">let</span> ms = <span class="keyword">new</span> <span class="title class_">MagicString</span>(source);</span><br><span class="line">            <span class="keyword">if</span> (imports.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; imports.<span class="property">length</span>; i++) &#123;</span><br><span class="line">                    <span class="keyword">let</span> &#123; s, e &#125; = imports[i];</span><br><span class="line">                    <span class="comment">// 应用的标识 vue  ./App.vue</span></span><br><span class="line">                    <span class="keyword">let</span> id = source.<span class="title function_">slice</span>(s, e); </span><br><span class="line">                    <span class="comment">// 不是./ 或者 /</span></span><br><span class="line">                    <span class="keyword">if</span> (<span class="regexp">/^[^\/\.]/</span>.<span class="title function_">test</span>(id)) &#123;</span><br><span class="line">                        id = <span class="string">`/@modules/<span class="subst">$&#123;id&#125;</span>`</span>;</span><br><span class="line">                        ms.<span class="title function_">overwrite</span>(s, e, id)</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> ms.<span class="title function_">toString</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        app.<span class="title function_">use</span>(<span class="keyword">async</span> (ctx, next) =&gt; &#123;</span><br><span class="line">            <span class="keyword">await</span> <span class="title function_">next</span>();   <span class="comment">// 静态服务</span></span><br><span class="line">            <span class="comment">// 默认会先执行 静态服务中间件 会将结果放到 ctx.body</span></span><br><span class="line">            <span class="comment">// 需要将流转换成字符串，只需要处理 js 中的引用问题</span></span><br><span class="line">            <span class="keyword">if</span> (ctx.<span class="property">body</span> &amp;&amp; ctx.<span class="property">response</span>.<span class="title function_">is</span>(<span class="string">&#x27;js&#x27;</span>)) &#123;</span><br><span class="line">                <span class="keyword">let</span> r = <span class="keyword">await</span> <span class="title function_">readBody</span>(ctx.<span class="property">body</span>);    <span class="comment">// vue =&gt; /@modules</span></span><br><span class="line">                <span class="keyword">const</span> result = <span class="title function_">rewriteImports</span>(r);</span><br><span class="line">                ctx.<span class="property">body</span> = result;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 2. 拦截包含 /@modules/vue 的请求，然后去 node_modules 引入对应模块并返回</span></span><br><span class="line">    <span class="function">(<span class="params">&#123; app, root &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> reg = <span class="regexp">/^\/@modules\//</span></span><br><span class="line">        app.<span class="title function_">use</span>(<span class="keyword">async</span> (ctx, next) =&gt; &#123;</span><br><span class="line">            <span class="comment">// 如果没有匹配到 /@modules/vue 就往下执行</span></span><br><span class="line">            <span class="keyword">if</span> (!reg.<span class="title function_">test</span>(ctx.<span class="property">path</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="title function_">next</span>();</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">const</span> id = ctx.<span class="property">path</span>.<span class="title function_">replace</span>(reg, <span class="string">&#x27;&#x27;</span>);</span><br><span class="line">            <span class="keyword">let</span> mapping = &#123;</span><br><span class="line">                <span class="attr">vue</span>: path.<span class="title function_">resolve</span>(root, <span class="string">&#x27;node_modules&#x27;</span>, </span><br><span class="line">                <span class="string">&#x27;@vue/runtime-dom/dist/runtime-dom.esm-browser.js&#x27;</span>),</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">const</span> content = <span class="keyword">await</span> fs.<span class="title function_">readFile</span>(mapping[id], <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line">            ctx.<span class="property">type</span> = <span class="string">&#x27;js&#x27;</span>;      <span class="comment">// 返回的文件是 js</span></span><br><span class="line">            ctx.<span class="property">body</span> = content;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 3. 解析.vue文件</span></span><br><span class="line">    <span class="function">(<span class="params">&#123; app, root &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">        app.<span class="title function_">use</span>(<span class="keyword">async</span> (ctx, next) =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span> (!ctx.<span class="property">path</span>.<span class="title function_">endsWith</span>(<span class="string">&#x27;.vue&#x27;</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="title function_">next</span>();</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">const</span> filePath = path.<span class="title function_">join</span>(root, ctx.<span class="property">path</span>);</span><br><span class="line">            <span class="keyword">const</span> content = <span class="keyword">await</span> fs.<span class="title function_">readFile</span>(filePath, <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line">            <span class="comment">// 引入 .vue 文件解析模板</span></span><br><span class="line">            <span class="keyword">const</span> &#123; compileTemplate, parse &#125; = <span class="built_in">require</span>(path.<span class="title function_">resolve</span>(root, </span><br><span class="line">            <span class="string">&#x27;node_modules&#x27;</span>, <span class="string">&#x27;@vue/compiler-sfc/dist/compiler-sfc.cjs&#x27;</span>))</span><br><span class="line">            <span class="keyword">let</span> &#123; descriptor &#125; = <span class="title function_">parse</span>(content);</span><br><span class="line">            <span class="keyword">if</span> (!ctx.<span class="property">query</span>.<span class="property">type</span>) &#123;</span><br><span class="line">                <span class="comment">// App.vue</span></span><br><span class="line">                <span class="keyword">let</span> code = <span class="string">&#x27;&#x27;</span></span><br><span class="line">                <span class="keyword">if</span> (descriptor.<span class="property">script</span>) &#123;</span><br><span class="line">                    <span class="keyword">let</span> desp = descriptor.<span class="property">script</span>.<span class="property">content</span>;</span><br><span class="line">                    code += desp.<span class="title function_">replace</span>(<span class="regexp">/((?:^|\n|;)\s*)export default/</span>, </span><br><span class="line">                    <span class="string">&#x27;$1const __script=&#x27;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (descriptor.<span class="property">template</span>) &#123;</span><br><span class="line">                    <span class="keyword">const</span> reqPath = ctx.<span class="property">path</span> + <span class="string">`?type=template`</span>;</span><br><span class="line">                    code += <span class="string">`\nimport &#123;render as __render&#125; from &quot;<span class="subst">$&#123;reqPath&#125;</span>&quot;`</span>;</span><br><span class="line">                    code += <span class="string">`\n__script.render = __render`</span></span><br><span class="line">                &#125;</span><br><span class="line">                code += <span class="string">`\nexport default __script`</span></span><br><span class="line">                ctx.<span class="property">type</span> = <span class="string">&#x27;js&#x27;</span>;</span><br><span class="line">                ctx.<span class="property">body</span> = code</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (ctx.<span class="property">query</span>.<span class="property">type</span> == <span class="string">&#x27;template&#x27;</span>) &#123;</span><br><span class="line">                ctx.<span class="property">type</span> = <span class="string">&#x27;js&#x27;</span>;</span><br><span class="line">                <span class="keyword">let</span> desp = descriptor.<span class="property">template</span>.<span class="property">content</span></span><br><span class="line">                <span class="comment">// 将 app.vue 中的模板 转换成 render 函数</span></span><br><span class="line">                <span class="keyword">const</span> &#123; code &#125; = <span class="title function_">compileTemplate</span>(&#123; <span class="attr">source</span>: desp &#125;); </span><br><span class="line">                ctx.<span class="property">body</span> = code;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 4. 静态服务插件 实现可以返回文件的功能</span></span><br><span class="line">    <span class="function">(<span class="params">&#123; app, root &#125;</span>) =&gt;</span> &#123;</span><br><span class="line">        app.<span class="title function_">use</span>(<span class="title function_">static</span>(root))</span><br><span class="line">        app.<span class="title function_">use</span>(<span class="title function_">static</span>(path.<span class="title function_">resolve</span>(root, <span class="string">&#x27;public&#x27;</span>)))</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">createServer</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> app = <span class="keyword">new</span> <span class="title class_">Koa</span>()</span><br><span class="line">    <span class="comment">// 创建一个用来给不同插件共享功能的上下文对象</span></span><br><span class="line">    <span class="keyword">const</span> context = &#123;     </span><br><span class="line">        app,</span><br><span class="line">        <span class="attr">root</span>: process.<span class="title function_">cwd</span>()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 运行中间件</span></span><br><span class="line">    resolvePlugin.<span class="title function_">forEach</span>(<span class="function"><span class="params">plugin</span> =&gt;</span> <span class="title function_">plugin</span>(context))</span><br><span class="line">    <span class="keyword">return</span> app</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">createServer</span>().<span class="title function_">listen</span>(<span class="number">4000</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Dev server running at:&#x27;</span>)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">` &gt; Local: <span class="subst">$&#123;chalk.cyan(<span class="string">&#x27;http://localhost:4000/&#x27;</span>)&#125;</span>`</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>


<h1 id="三、组件开发"><a href="#三、组件开发" class="headerlink" title="三、组件开发"></a>三、组件开发</h1><blockquote>
<p>根据功能可分为展示组件和容器组件，根据定义方式可分为函数组件和类组件，根据状态可分为无状态组件和有状态组件。React 组件使用 state 来管理自身数据并通过 props 来接收外部数据，为了实现对数据变更做出响应而采用 Class 组件并提供了生命周期和一系列 API。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 基于 Class 设计组件</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyConponent</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="comment">// 组件数据</span></span><br><span class="line">    state = &#123; <span class="attr">counts</span>: <span class="number">0</span> &#125;</span><br><span class="line">    <span class="comment">// 响应数据变更</span></span><br><span class="line">    clickHandle = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; <span class="attr">counts</span>: <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">counts</span>++ &#125;);</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">onClick</span>) <span class="variable language_">this</span>.<span class="property">props</span>.<span class="title function_">onClick</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 生命周期钩子</span></span><br><span class="line">    <span class="title function_">componentWillUnmount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Will mouned!&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 接收外部数据并显示</span></span><br><span class="line">    <span class="title function_">render</span>(<span class="params">props</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="language-xml">              <span class="tag">&lt;<span class="name">span</span>&gt;</span>Input content: &#123;props.content&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">              <span class="tag">&lt;<span class="name">span</span>&gt;</span>btn click counts: &#123;this.state.counts&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">              <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.clickHandle&#125;</span>&gt;</span>Add<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="组件创建"><a href="#组件创建" class="headerlink" title="组件创建"></a>组件创建</h2><blockquote>
<p>组件名的首字母必须大写，因为 JSX 转换时会调用 <code>React.createElement(type, config, children)</code>。type 声明了元素类型：首字母大写时会被 babel 看作一个组件而传入变量，小写时则看作一个 html 标签而传入字符串。</p>
</blockquote>
<ul>
<li><strong>函数式创建无状态组件</strong>：组件不会被实例化而整体渲染性能较好(推荐尽量使用)、组件不能操作 state 而且不能访问生命周期和 this。</li>
<li><strong>ES5 原生方式已废弃</strong>：每个成员函数的 this 都会由 React 自动绑定而导致不必要的性能开销、创建组件时可以添加 mixins 属性并将可供混合的所有类的数组形式赋给它。</li>
<li><strong>ES6 创建有状态组件</strong>：成员函数需要开发者手动绑定否则会让 this 不能获取当前组件的实例对象、state 是在 constructor 中实现初始化、props 属性和默认属性作为组件类的属性并不是组件实例的属性所以使用类的静态属性配置。</li>
<li><strong>其它方式</strong>：高阶组件(一个接收原组件为参数并返回新组件的纯函数)、Hooks。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数组件：写法简洁，应尽量使用，但是功能单一</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">MyCom</span>(<span class="params">props</span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>mycomponent<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ES5 原生</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">MyCom</span> = <span class="title class_">React</span>.<span class="title function_">createClass</span>(&#123;</span><br><span class="line">    <span class="title function_">getInitialState</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">message</span>: <span class="string">&#x27;Hi&#x27;</span> &#125;;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">log</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">message</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;button&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Log&quot;</span> <span class="attr">onClick</span>=<span class="string">&#123;this.log&#125;</span> /&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 类组件：官方推荐，可以维护状态变量和实现复杂功能</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyCom</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 正常写法：有 constructor 则必须有 super</span></span><br><span class="line">    <span class="comment">// super 指父类构造函数 React.Component，传参后会初始化 props</span></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props</span>)&#123;</span><br><span class="line">        <span class="variable language_">super</span>(props);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> =  &#123; <span class="attr">name</span>: <span class="string">&quot;&quot;</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 简写写法</span></span><br><span class="line">    state =  &#123; <span class="attr">name</span>: <span class="string">&quot;&quot;</span> &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; <span class="attr">name</span>: <span class="string">&quot;William&quot;</span> &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>this.state.name<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 高阶组件</span></span><br><span class="line"><span class="keyword">import</span> &#123;withRouter&#125; <span class="keyword">from</span> <span class="string">&#x27;react-router-dom&#x27;</span>;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    state = &#123; <span class="attr">path</span>: <span class="string">&#x27;&#x27;</span> &#125;</span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> path = <span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">location</span>.<span class="property">pathname</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; path &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>rendering at: &#123;this.state.path&#125;<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">withRouter</span>(<span class="title class_">App</span>)</span><br></pre></td></tr></table></figure>

<h2 id="事件绑定"><a href="#事件绑定" class="headerlink" title="事件绑定"></a>事件绑定</h2><blockquote>
<p>将事件绑定到 this。</p>
</blockquote>
<ol>
<li><strong>constructor + bind</strong>：只需要在构造函数中预先绑定一次</li>
<li><strong>render + bind</strong>：每次渲染时都需要重新绑定，存在性能问题</li>
<li><strong>ES6 箭头函数</strong>：只能在 render 添加，存在性能问题并且不能移除监听事件。</li>
<li><strong>ES7 箭头函数</strong>：ES6 优化方案，可以在 Class 中直接赋值。需要安装 babel-preset-stage-2 并配置 <code>.babelrc：&quot;presets&quot;:[&quot;react&quot;,&quot;env&quot;,&quot;stage-2&quot;]</code>。</li>
</ol>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props)</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">msg</span>: <span class="string">&quot;hello&quot;</span> &#125;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">logMsg</span> = <span class="variable language_">this</span>.<span class="property">logMsg</span>.<span class="title function_">bind</span>(<span class="variable language_">this</span>)  <span class="comment">// 1</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">logMsg</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">msg</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    _logMsg = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">message</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.logMsg&#125;</span>&gt;</span>1<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.logMsg.bind(this)&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> this.logMsg()&#125;&gt;3<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this._logMsg&#125;</span>&gt;</span>4<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h2>  <div align="center">
      <img src="" data-original="/images/frame/life_cycle.png" alt="生命周期执行顺序" width="100%">
  </div>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// react-v16.3 之前版本</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 1、组件挂载：组件第一次渲染到 Dom 树</span></span><br><span class="line">  constructor</span><br><span class="line">  componentWillMount</span><br><span class="line">  render</span><br><span class="line">  componentDidMount</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 2、组件更新：组件 state、props 变化引发的重新渲染</span></span><br><span class="line">  componentWillReceiveProps</span><br><span class="line">  shouldComponentUpdate</span><br><span class="line">  componentWillUpdate</span><br><span class="line">  render</span><br><span class="line">  componentDidUpdate</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 3、组件卸载：组件从 Dom 树删除</span></span><br><span class="line">  componentWillUnmount</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// react-v16.3 版本</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 新增</span></span><br><span class="line">  <span class="comment">// 组件实例化时或 props 变化时调用，返回新对象作为新 state，返回 null 则不更新</span></span><br><span class="line">  <span class="keyword">static</span> <span class="title function_">getDerivedStateFromProps</span>(<span class="params">nextProps, prevState</span>)&#123;&#125;</span><br><span class="line">  <span class="comment">// DOM 更新完成前被调用，返回值是 componentDidUpdate 的第三个参数</span></span><br><span class="line">  <span class="title function_">getSnapshotBeforeUpdate</span>(<span class="params">prevProps, prevState</span>)&#123;&#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 废弃</span></span><br><span class="line">  componentWillMount   <span class="comment">// 预装载函数：不能进行修改 state 的操作</span></span><br><span class="line">  componentWillReceiveProps  <span class="comment">// props 变化时调用，常用于根据新旧数据设置组件状态</span></span><br><span class="line">  componentWillUpdate  <span class="comment">// 预更新函数：此时不能修改属性和状态</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 1、组件挂载</span></span><br><span class="line">  constructor   <span class="comment">// 实例化：初始化 state，本地化 props，给事件处理函数绑定 this</span></span><br><span class="line">  <span class="keyword">static</span> getDerivedStateFromProps</span><br><span class="line">  render        <span class="comment">// 渲染函数：不能省略并且必须有返回值 (返回 null/false 表示不渲染)</span></span><br><span class="line">  componentDidMount  <span class="comment">// 挂载完成函数：axios、事件绑定、setState 数据、操作 dom</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 2、组件更新</span></span><br><span class="line">  <span class="keyword">static</span> getDeriverdStateFromProps  <span class="comment">// 从 props 中获取 state</span></span><br><span class="line">  shouldComponentUpdate    <span class="comment">// 返回 true/false 表示是否更新，常用于组件性能优化</span></span><br><span class="line">  render                   <span class="comment">// 渲染</span></span><br><span class="line">  getSnapshotBeforeUpdate  <span class="comment">// 获取快照</span></span><br><span class="line">  componentDidUpdate       <span class="comment">// 更新完成函数</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 3、组件卸载</span></span><br><span class="line">  componentWillUnmount     <span class="comment">// 预销毁函数：移除定时器、事件绑定等</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 4、错误处理</span></span><br><span class="line">  <span class="keyword">static</span> getDerivedStateFromError <span class="comment">// 从错误中获取 state</span></span><br><span class="line">  componentDidCatch        <span class="comment">// 捕获错误并进行处理</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="组件-API"><a href="#组件-API" class="headerlink" title="组件 API"></a>组件 API</h2><blockquote>
<p>npm install react 时加载。组件接收 props 并返回描述渲染逻辑的 React 元素，React 通过传入参数即可渲染出对应页面，这是 React 被称为声明性 API 的原因。</p>
</blockquote>
<ul>
<li><code>render</code>：class 方式创建组件时用于实例化组件(转换格式并插入到指定节点)的渲染函数，props&#x2F;state 被改变时就会重新执行，shouldComponentUpdate 返回 false 时不会执行。</li>
<li><code>state</code>：用于存储组件内部数据，更新时通过 this.setState()、useState。setState 在钩子函数和基于原生事件封装的合成事件中无法获取最新值并且在合成事件中执行多次时只会执行一次，这是因为它们的调用顺序在更新之前而且 setState 源码本身是同步的。</li>
<li><code>props</code>：继承父组件属性和方法的对外接口，数据是只读的但可以限制其类型和默认值。</li>
<li><code>Context</code>：组件树从上至下逐层自动传递的上下文对象，避免了在每个层级都需要手动传递 props。实现原理为基于生产者消费者模式创建一个包含两个组件的上下文对象：Provider (生产者：定义数据的父组件)、Consumer (消费者：使用数据的子孙组件)。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、render：组件渲染</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">ReactDOM</span> <span class="keyword">from</span> <span class="string">&quot;react-dom&quot;</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Header</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    state = &#123; <span class="attr">path</span>: <span class="string">&#x27;&#x27;</span> &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>rendering at: &#123;this.state.path&#125;<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">ReactDOM</span>.<span class="title function_">render</span>(<span class="language-xml"><span class="tag">&lt;<span class="name">Header</span> /&gt;</span></span>, <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;root&#x27;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span>  路由渲染</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@method</span> component: 属性值是一个组件，URL、Route 匹配时就会被渲染</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@method</span> render: 属性值是一个返回 jsx 元素的函数，方便为组件传递额外属性</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@method</span> children: 同上，区别是返回组件一定会渲染，不匹配时 match: null</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/foo&#x27;</span> <span class="attr">component</span>=<span class="string">&#123;FOO&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/foo&#x27;</span> <span class="attr">render</span>=<span class="string">&#123;props</span>=&gt;</span>(</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Foo</span> &#123;<span class="attr">...props</span>&#125; <span class="attr">data</span>=<span class="string">&#123;extraProps&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/foo&#x27;</span> <span class="attr">children</span>=<span class="string">&#123;props</span>=&gt;</span>(</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&#123;props.match</span> ? &#x27;<span class="attr">active</span>&#x27;<span class="attr">:</span> &#x27;&#x27;&#125;&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">Foo</span> &#123;<span class="attr">...props</span>&#125; <span class="attr">data</span>=<span class="string">&#123;extraProps&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">)&#125; /&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、state</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">MyCom</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    state = &#123; <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>, <span class="attr">age</span>: <span class="number">20</span> &#125;</span><br><span class="line">    handle (option, value)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; [option]: value &#125;, <span class="function">()=&gt;</span>&#123;</span><br><span class="line">            <span class="comment">// 状态更新后的回调函数，重新渲染后执行</span></span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span> this.handle(&quot;name&quot;)&#125;&gt;点击<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、props：传递数据和事件</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">PropTypes</span> <span class="keyword">from</span> <span class="string">&#x27;prop-types&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">Block</span> ()&#123;</span><br><span class="line">    <span class="keyword">const</span> name = <span class="string">&quot;Mary&quot;</span></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleDelete</span> = (<span class="params"></span>) =&gt; &#123; &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Name</span> <span class="attr">name</span>=<span class="string">&#123;name&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">DeletableBlock</span> <span class="attr">onDelete</span>=<span class="string">&#123;handleDelete&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">Name</span> (&#123;name&#125;)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">span</span>&gt;</span>&#123;name&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">DeletableBlock</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; children, onDelete &#125; = props;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;delete&quot;</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span> onDelete()&#125;&gt;清空<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Name</span>.<span class="property">propTypes</span> = &#123; <span class="attr">name</span>: <span class="title class_">PropTypes</span>.<span class="property">string</span> &#125;</span><br><span class="line"><span class="title class_">Name</span>.<span class="property">defaultProps</span> = &#123; <span class="attr">name</span>: <span class="string">&#x27;Mary&#x27;</span> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 4、Context</span></span><br><span class="line"><span class="comment">// index.js：父组件</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Son</span> <span class="keyword">from</span> <span class="string">&#x27;./son&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> &#123;<span class="title class_">Provider</span>, <span class="title class_">Consumer</span>&#125; = <span class="title class_">React</span>.<span class="title function_">createContext</span>(<span class="string">&quot;value默认值&quot;</span>);</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> name = <span class="string">&quot;context 通信&quot;</span></span><br><span class="line">        <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">Provider</span> <span class="attr">value</span>=<span class="string">&#123;name&#125;</span>&gt;</span> <span class="tag">&lt;<span class="name">Son</span> /&gt;</span> <span class="tag">&lt;/<span class="name">Provider</span>&gt;</span></span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// son.js：子组件、孙组件</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Consumer</span> &#125; <span class="keyword">from</span> <span class="string">&quot;./index&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">Son</span>(<span class="params">props</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">Consumer</span>&gt;</span>&#123;name=&gt; <span class="tag">&lt;<span class="name">div</span>&gt;</span>子组件接收：&#123;name&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span> &#125;<span class="tag">&lt;/<span class="name">Consumer</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="Ref-用法"><a href="#Ref-用法" class="headerlink" title="Ref 用法"></a>Ref 用法</h2><blockquote>
<p>类组件使用时可通过 String-Ref、Callback-Ref、createRef，没有实例的函数式组件则可通过 React16.3 版本才引入的新接口 useRef、forwardRef、useImperativeHandle。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、String Ref：只能用于类组件而且不安全的字符串方式，已被淘汰</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; <span class="title class_">Component</span>, createRef &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">refs</span>.<span class="property">h1Ref</span>, <span class="variable language_">this</span>.<span class="property">refs</span>.<span class="property">childRef</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">h1</span> <span class="attr">ref</span>=<span class="string">&#x27;h1Ref&#x27;</span>&gt;</span>Hello World!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">Child</span> <span class="attr">ref</span>=<span class="string">&#x27;childRef&#x27;</span> <span class="attr">count</span>=<span class="string">&#x27;1&#x27;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span> </span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    handleLog = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Child Component&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> &#123; count &#125; = <span class="variable language_">this</span>.<span class="property">props</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>count: &#123; count &#125;<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、Callback Ref：接受组件实例或元素作为参数的回调函数形式</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">h1Ref</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">h1</span> <span class="attr">ref</span>=<span class="string">&#123;ele</span> =&gt;</span> (this.h1Ref = ele)&#125;&gt;Hello<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">Child</span> <span class="attr">ref</span>=<span class="string">&#123;com</span> =&gt;</span> (this.childRef = com)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、createRef：类组件中推荐使用的创建方式</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">props</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>(props);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">h1Ref</span> = <span class="title function_">createRef</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">h1Ref</span>.<span class="property">current</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">ref</span>=<span class="string">&#123;this.h1Ref&#125;</span>&gt;</span>Hello<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 4、useRef：创建一个持久可变的 ref 对象，但更新时不会触发组件重新渲染</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useEffect, useRef &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> inputRef = <span class="title function_">useRef</span>(<span class="literal">null</span>);</span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(inputRef.<span class="property">current</span>.<span class="property">value</span>)</span><br><span class="line">    &#125;, [])</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">ref</span>=<span class="string">&#123;inputRef&#125;</span> /&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 5、forwardRef：转发 refs 到 DOM 组件、高阶组件中转发 refs</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">FancyButton</span> = <span class="title class_">React</span>.<span class="title function_">forwardRef</span>(<span class="function">(<span class="params">props, ref</span>) =&gt;</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">ref</span>=<span class="string">&#123;ref&#125;</span> <span class="attr">className</span>=<span class="string">&quot;FancyButton&quot;</span>&gt;</span>&#123;props.children&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line">));</span><br><span class="line"><span class="keyword">const</span> ref = <span class="title class_">React</span>.<span class="title function_">createRef</span>();   <span class="comment">// FancyButton 组件可获取底层 button ref</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">FancyButton</span> <span class="attr">ref</span>=<span class="string">&#123;ref&#125;</span>&gt;</span>Click<span class="tag">&lt;/<span class="name">FancyButton</span>&gt;</span></span>;  </span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">logProps</span>(<span class="params">Component</span>) &#123;</span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">LogProps</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">        <span class="title function_">componentDidUpdate</span>(<span class="params">prevProps</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;old props:&#x27;</span>, prevProps);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;new props:&#x27;</span>, <span class="variable language_">this</span>.<span class="property">props</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> &#123;forwardedRef, ...rest&#125; = <span class="variable language_">this</span>.<span class="property">props</span>;</span><br><span class="line">            <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">Component</span> <span class="attr">ref</span>=<span class="string">&#123;forwardedRef&#125;</span> &#123;<span class="attr">...rest</span>&#125; /&gt;</span></span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 参数值当作常规属性传递给 LogProps，即可被挂载到它包裹的子组件。</span></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">ForwardRef</span> = (<span class="params">props, ref</span>) =&gt; (</span><br><span class="line">        <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">LogProps</span> &#123;<span class="attr">...props</span>&#125; <span class="attr">forwardedRef</span>=<span class="string">&#123;ref&#125;</span> /&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">    <span class="keyword">const</span> name = <span class="title class_">Component</span>.<span class="property">displayName</span> || <span class="title class_">Component</span>.<span class="property">name</span>;</span><br><span class="line">    <span class="title class_">ForwardRef</span>.<span class="property">displayName</span> = <span class="string">`logProps(<span class="subst">$&#123;name&#125;</span>)`</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">React</span>.<span class="title function_">forwardRef</span>(<span class="title class_">ForwardRef</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 6、useImperativeHandle(ref, createHandle, [deps])：自定义 Hook。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 访问子组件的实例：父组件通过 ref 获取 createHandle 暴露出的方法和属性。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 访问原生 DOM 元素的方法：createHandle 定义滚动到指定位置等 DOM 方法。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 子组件集成第三方库的方法：父组件在 createHandle 调用该库的方法并返回。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 控制子组件的动画或转换效果：父组件可通过调用 createHandle 定义的接口。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="comment">// 子组件</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Draggable</span> <span class="keyword">from</span> <span class="string">&#x27;react-draggable&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useRef, forwardRef, useImperativeHandle &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">ChildComponent</span> = <span class="title function_">forwardRef</span>(<span class="function">(<span class="params">props, ref</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> childRef = <span class="title function_">useRef</span>();</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleClick</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Button clicked&#x27;</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">scrollToTop</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        childRef.<span class="property">current</span>.<span class="property">scrollTop</span> = <span class="number">0</span>;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">resetPosition</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        <span class="title class_">Draggable</span>.<span class="title function_">resetPosition</span>();</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">fadeIn</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        childRef.<span class="property">current</span>.<span class="property">style</span>.<span class="property">opacity</span> = <span class="number">1</span>;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="title function_">useImperativeHandle</span>(ref, <span class="function">() =&gt;</span> (&#123;</span><br><span class="line">        handleClick,</span><br><span class="line">        scrollToTop,</span><br><span class="line">        resetPosition</span><br><span class="line">    &#125;));</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">ref</span>=<span class="string">&#123;childRef&#125;</span> <span class="attr">style</span>=<span class="string">&#123;&#123;height:</span> &#x27;<span class="attr">20</span>&#x27;, <span class="attr">overflowY:</span> &#x27;<span class="attr">scroll</span>&#x27;&#125;&#125;&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;handleClick&#125;</span>&gt;</span>Click<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 父组件</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">ChildComponent</span> <span class="keyword">from</span> <span class="string">&#x27;./ChildComponent&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">ParentComponent</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> childRef = <span class="title function_">useRef</span>();</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleButtonClick</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        childRef.<span class="property">current</span>.<span class="title function_">handleClick</span>();</span><br><span class="line">        childRef.<span class="property">current</span>.<span class="title function_">scrollToTop</span>();</span><br><span class="line">        childRef.<span class="property">current</span>.<span class="title function_">resetPosition</span>();</span><br><span class="line">        childRef.<span class="property">current</span>.<span class="title function_">fadeIn</span>();</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">ChildComponent</span> <span class="attr">ref</span>=<span class="string">&#123;childRef&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;handleButtonClick&#125;</span>&gt;</span>Click<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>


<h2 id="组件通信"><a href="#组件通信" class="headerlink" title="组件通信"></a>组件通信</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 父传子：自定义属性 + props</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 子传父：自定义函数 + props</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 传向后代跨层级组件：context</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 非关系组件传递：Refs、Context、EventBus、订阅发布模式</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 状态管理库：Redux、Mobx、Recoil、React-Query 等等</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="comment">// DataContext.js</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">DataContext</span> = <span class="title class_">React</span>.<span class="title function_">createContext</span>();</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">DataContext</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// bus.js</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">EventEmitter</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;events&#x27;</span></span><br><span class="line"><span class="keyword">const</span> eventBus = <span class="keyword">new</span> <span class="title class_">EventEmitter</span>()</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> eventBus</span><br><span class="line"></span><br><span class="line"><span class="comment">// Parent.jsx</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Child</span> <span class="keyword">from</span> <span class="string">&#x27;./Child&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> eventBus <span class="keyword">from</span> <span class="string">&#x27;./bus&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">DataContext</span> <span class="keyword">from</span> <span class="string">&#x27;./DataContext&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Parent</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> name = <span class="string">&#x27;parent&#x27;</span></span><br><span class="line">    <span class="keyword">const</span> [message, setMessage] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleMsg</span> = (<span class="params">msg</span>) =&gt; &#123;</span><br><span class="line">        <span class="title function_">setMessage</span>(msg);</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleClick</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        eventBus.<span class="title function_">emit</span>(<span class="string">&#x27;dbclick&#x27;</span>, <span class="string">&#x27;发送事件&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">p</span>&gt;</span>子组件数据：&#123;message&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">Child</span> <span class="attr">name</span>=<span class="string">&#x27;parent&#x27;</span> <span class="attr">ref</span>=<span class="string">&#x27;child&#x27;</span> <span class="attr">onMessage</span>=<span class="string">&#123;handleMsg&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">DataContext.Provider</span> <span class="attr">value</span>=<span class="string">&#123;name&#125;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Child</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">DataContext.Provider</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Child.jsx</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> eventBus <span class="keyword">from</span> <span class="string">&#x27;./bus&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">DataContext</span> <span class="keyword">from</span> <span class="string">&#x27;./DataContext&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Child</span> = (<span class="params">props</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">onClick</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        props.<span class="title function_">onMessage</span>(<span class="string">&#x27;child&#x27;</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleClick</span> = val =&gt; &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;val&#x27;</span>, val);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        eventBus.<span class="title function_">on</span>(<span class="string">&#x27;dbclick&#x27;</span>, handleClick)</span><br><span class="line">        <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            eventBus.<span class="title function_">off</span>(<span class="string">&#x27;dbclick&#x27;</span>, handleClick)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;, [])</span><br><span class="line">    <span class="keyword">const</span> value = <span class="title function_">useContext</span>(<span class="title class_">DataContext</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;onClick&#125;</span>&gt;</span>&#123;props.name&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> bus <span class="keyword">from</span> <span class="string">&#x27;./bus&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">A</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleClick</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        bus.<span class="title function_">emit</span>(<span class="string">&#x27;click&#x27;</span>, <span class="string">&#x27;爱在西元前&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;&gt;</span><span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;handleClick&#125;</span>&gt;</span>click<span class="tag">&lt;/<span class="name">button</span>&gt;</span><span class="tag">&lt;/&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// Refs 父组件调用子组件方法：useImperativeHandle 暴露子组件的方法</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Child</span> <span class="keyword">from</span> <span class="string">&quot;./child&quot;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useRef &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">Father</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> myRef = <span class="title function_">useRef</span>()</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">handleClick</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        myRef.<span class="property">current</span>.<span class="title function_">handleClick</span>()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">Child</span> <span class="attr">ref</span>=<span class="string">&#123;myRef&#125;</span> <span class="attr">onClick</span>=<span class="string">&#123;handleClick&#125;</span> /&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useImperativeHandle, forwardRef &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Child</span> = (<span class="params">props, ref</span>) =&gt; &#123;</span><br><span class="line">    <span class="title function_">useImperativeHandle</span>(ref, <span class="function">() =&gt;</span> (&#123;</span><br><span class="line">        <span class="attr">handleClick</span>: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;点击&#x27;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;))</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>子组件<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">forwardRef</span>(<span class="title class_">Child</span>)</span><br></pre></td></tr></table></figure>


<h1 id="五、路由功能"><a href="#五、路由功能" class="headerlink" title="五、路由功能"></a>五、路由功能</h1><blockquote>
<p>react-router-4.0 (以下简称 RR4) 采用单代码仓库模型架构，包含了若干相互独立的包。注意：react-router-dom&#x2F;native 已经包含了 react-router 的依赖，使用时不需要安装和引用 react-router。</p>
</blockquote>
<ul>
<li><strong>react-router</strong>：核心公用组件和方法。具体有：MemoryRouter、Prompt、Redirect、Route、RouterStaticRouter、 Switch、matchPath、withRouter。</li>
<li><strong>react-router-dom</strong>：用于 web 环境开发，提供了 dom 操作控制路由的主要方法有 BrowserRouter、 HashRouter、 Link 、NavLink。</li>
<li><strong>react-router-native</strong>：用于给 native 相关应用提供路由支持，主要有 NativeRouter、 Link、 DeepLinkingAndroidBackButton。</li>
<li><strong>react-router-redux</strong>：React Router 和 Redux 的集成。</li>
<li><strong>react-router-config</strong>：集中配置静态路由，主要有 matchRoutes、renderRoutes。</li>
</ul>
<h2 id="路由组件"><a href="#路由组件" class="headerlink" title="路由组件"></a>路由组件</h2><blockquote>
<p>所有与路由有关的组件（Link、NavLink、Route、Switch）必须包裹在容器组件中，容器组件有且只能有一个子元素。</p>
</blockquote>
<ul>
<li>容器组件<ul>
<li><strong>BrowserRouter</strong>：浏览器的路由组件，利用 HTML5 的 history API (pushState、replaceState 和 popstate 事件) 来同步 URL、UI。需要添加服务器配置 (node&#x2F;nginx)，让前端请求映射到对应的 html。</li>
<li><strong>HashRouter</strong>：使用 URL hash (window.location.hash) 方式在前端完成路由切换。<code>#</code> 后面的内容不会发送到服务器端，路由地址对于后端始终不变。</li>
<li><strong>MemoryRouter</strong>：内存路由组件，在内存中管理 URL history，主要用于 ReactNative 这种非浏览器的环境。</li>
<li><strong>StaticRouter</strong>：地址不改变的静态路由组件，主要用于服务端渲染。</li>
<li><strong>NativeRouter</strong>：Native 的路由组件。</li>
</ul>
</li>
<li>相关组件<ul>
<li><strong>Link</strong>：react-router 提供，用于点击时链接到某路径。</li>
<li><strong>NavLink</strong>：Link 的加强版，可以自定义选中状态和钩子函数。</li>
<li><strong>Switch</strong>：用于嵌套 Route 组件，多个路径相同时只匹配第一个。</li>
<li><strong>Route</strong>：用于实现 RR4 动态路由的嵌套。</li>
<li><strong>Redirect</strong>：用于重定向到某路径。</li>
</ul>
</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">&lt;<span class="title class_">BrowserRouter</span> </span><br><span class="line">    basename=<span class="string">&quot;/admin&quot;</span>     <span class="comment">// 路由器的默认根路径</span></span><br><span class="line">    forceRefresh=&#123;<span class="literal">false</span>&#125;  <span class="comment">// 布尔类型，导航时是否刷新整个页面</span></span><br><span class="line">    keyLength=&#123;<span class="number">12</span>&#125;        <span class="comment">// location.key 的长度，默认 6</span></span><br><span class="line">    getUserConfirmation=&#123;getConfirmation&#125;  <span class="comment">// 导航需要确认时执行的函数</span></span><br><span class="line">&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&quot;/home&quot;</span>/&gt;</span></span>   <span class="comment">// 渲染为 &lt;a href=&quot;/admin/home&quot;&gt;</span></span><br><span class="line">&lt;/<span class="title class_">BrowserRouter</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 覆盖当前路径</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&quot;/about&quot;</span> <span class="attr">replace</span>=<span class="string">&#123;true&#125;</span>&gt;</span>关于<span class="tag">&lt;/<span class="name">Link</span>&gt;</span></span> </span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&#123;&#123;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">pathname:</span> &#x27;/<span class="attr">courses</span>&#x27;,</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">search:</span> &#x27;?<span class="attr">sort</span>=<span class="string">name</span>&#x27;,  // <span class="attr">下个页面取值</span>：<span class="attr">props.location.state</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">hash:</span> &#x27;#<span class="attr">the-hash</span>&#x27;,</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">state:</span> &#123; <span class="attr">fromDashboard:</span> <span class="attr">true</span> &#125;</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">&#125;&#125;/&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 当 event id 为奇数的时候，激活链接</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">activeEvent</span> = (<span class="params">match, location</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (!match) &#123; <span class="keyword">return</span> <span class="literal">false</span> &#125;</span><br><span class="line">    <span class="keyword">const</span> eventID = <span class="built_in">parseInt</span>(match.<span class="property">params</span>.<span class="property">eventID</span>)</span><br><span class="line">    <span class="keyword">return</span> !<span class="built_in">isNaN</span>(eventID) &amp;&amp; eventID % <span class="number">2</span> === <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line">&lt;<span class="title class_">NavLink</span></span><br><span class="line">    to=<span class="string">&quot;/home?ask&quot;</span> </span><br><span class="line">    exact  <span class="comment">// 是否严格匹配</span></span><br><span class="line">    activeClassName=<span class="string">&quot;selected&quot;</span> </span><br><span class="line">    activeStyle=&#123;&#123; <span class="attr">color</span>: <span class="string">&#x27;green&#x27;</span>, <span class="attr">fontWeight</span>: <span class="string">&#x27;bold&#x27;</span> &#125;&#125;</span><br><span class="line">    isActive=&#123;activeEvent&#125;  <span class="comment">// 判断链接是否激活的额外逻辑</span></span><br><span class="line">&gt;问答&lt;/<span class="title class_">NavLink</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Route</span> </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">exact</span>                // <span class="attr">是否完全匹配</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">strict</span>               // <span class="attr">path</span> <span class="attr">有结尾斜线只能匹配有斜线的路径</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">path</span>=<span class="string">&quot;/peoples/&quot;</span>     // <span class="attr">路由匹配路径</span> (<span class="attr">不能匹配</span> /<span class="attr">peoples</span>)</span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">component</span>=<span class="string">&#123;Peoples&#125;</span>  // <span class="attr">URL</span>、<span class="attr">Route</span> <span class="attr">匹配时渲染的组件</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">&gt;</span><span class="tag">&lt;<span class="name">Route</span>/&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    &#123;/* 进入客户管理页面，默认展示 List 区域内容，或者使用重定向 */&#125;</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/custom&#x27;</span> <span class="attr">exact</span> <span class="attr">component</span>=<span class="string">&#123;List&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">Route</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/custom/list&#x27;</span> <span class="attr">component</span>=<span class="string">&#123;List&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">Route</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/custom/create&#x27;</span> <span class="attr">component</span>=<span class="string">&#123;Create&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">Route</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#x27;/custom/Detail/:id&#x27;</span> <span class="attr">component</span>=<span class="string">&#123;Detail&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">Route</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    &#123;/* <span class="tag">&lt;<span class="name">Redirect</span> <span class="attr">from</span>=<span class="string">&#x27;/custom&#x27;</span> <span class="attr">to</span>=<span class="string">&#x27;/custom/list&#x27;</span>&gt;</span><span class="tag">&lt;/<span class="name">Redirect</span>&gt;</span> */&#125;</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Redirect</span> <span class="attr">to</span>=<span class="string">&#123;&#123;</span> <span class="attr">pathname:</span> &#x27;/<span class="attr">log</span>&#x27;, <span class="attr">search:</span> &#x27;?<span class="attr">name</span>=<span class="string">a</span>&#x27;, <span class="attr">state:</span>&#123;<span class="attr">id:</span> <span class="attr">1</span>&#125; &#125;&#125; /&gt;</span></span></span><br></pre></td></tr></table></figure>


<h2 id="路由对象"><a href="#路由对象" class="headerlink" title="路由对象"></a>路由对象</h2><blockquote>
<p>被 Route 绑定的渲染组件，总是被传入三个属性（对象）：history、location、match。在渲染组件中也会有很多其他组件，这些组件内部如果想要获取三个对象，需要 withRouter（通过装饰器或函数调用的形式都可以）。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// history：用于编程式导航</span></span><br><span class="line"><span class="keyword">let</span> &#123; history &#125; = <span class="variable language_">this</span>.<span class="property">props</span></span><br><span class="line">history.<span class="title function_">push</span>()       <span class="comment">// 追加一条记录   </span></span><br><span class="line">history.<span class="title function_">replace</span>()    <span class="comment">// 不会追加记录   </span></span><br><span class="line">history.<span class="title function_">goback</span>()     <span class="comment">// 回退</span></span><br><span class="line">history.<span class="title function_">goforward</span>()  <span class="comment">// 前进</span></span><br><span class="line">history.<span class="title function_">go</span>(n)</span><br><span class="line"></span><br><span class="line"><span class="comment">// loaction：指当前位置</span></span><br><span class="line"><span class="keyword">let</span> &#123; <span class="attr">location</span>: &#123; pathname, search, state&#125; &#125; = <span class="variable language_">this</span>.<span class="property">props</span>;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&#123;location&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">NaviveLink</span> <span class="attr">to</span>=<span class="string">&#123;location&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Redirect</span> <span class="attr">to</span>=<span class="string">&#123;location</span> /&gt;</span></span></span><br><span class="line">history.<span class="title function_">push</span>(location)</span><br><span class="line">history.<span class="title function_">replace</span>(location)</span><br><span class="line"></span><br><span class="line"><span class="comment">// match：包含了路由匹配的信息</span></span><br><span class="line"><span class="keyword">let</span> &#123; <span class="attr">match</span>: &#123; params &#125; &#125; = <span class="variable language_">this</span>.<span class="property">props</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(params.<span class="property">id</span>)</span><br></pre></td></tr></table></figure>


<h2 id="路由传参"><a href="#路由传参" class="headerlink" title="路由传参"></a>路由传参</h2><blockquote>
<p>不推荐：localstroage、redux（页面刷新后会丢失数据）。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、params</span></span><br><span class="line">&lt;<span class="title class_">Route</span> path=<span class="string">&#x27;/user/:id&#x27;</span> component=&#123;<span class="title class_">User</span>&#125; /&gt;  <span class="comment">// 路由设置</span></span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&#x27;/user/2&#x27;</span> /&gt;</span></span>                 <span class="comment">// 传值一</span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">history</span>.<span class="title function_">push</span>(<span class="string">&quot;/user/2&quot;</span>);   <span class="comment">// 传值2二</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">match</span>.<span class="property">params</span>.<span class="property">id</span>     <span class="comment">// 获取值</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、URL参数</span></span><br><span class="line">&lt;<span class="title class_">Route</span> path=<span class="string">&#x27;/user&#x27;</span> component=&#123;<span class="title class_">User</span>&#125; /&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&#x27;/user?id=2&#x27;</span> /&gt;</span></span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">location</span>.<span class="property">query</span>.<span class="property">id</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、location 对象（哈希路由不支持）</span></span><br><span class="line">&lt;<span class="title class_">Route</span> path=<span class="string">&#x27;/user&#x27;</span> component=&#123;<span class="title class_">User</span>&#125;&gt;&lt;/<span class="title class_">Route</span>&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">Link</span> <span class="attr">to</span>=<span class="string">&#123;&#123;pathname:</span>&#x27; /<span class="attr">u</span>&#x27;, <span class="attr">state:</span> &#123;<span class="attr">id:1</span>&#125;, <span class="attr">search:</span>&#x27;?<span class="attr">sort</span>=<span class="string">a</span>&#x27;, <span class="attr">hash:</span>&#x27;#<span class="attr">h</span>&#x27;&#125;&#125; /&gt;</span></span></span><br><span class="line"><span class="variable language_">this</span>.<span class="property">props</span>.<span class="property">location</span>.<span class="property">state</span>.<span class="property">id</span></span><br></pre></td></tr></table></figure>


<h2 id="基础使用"><a href="#基础使用" class="headerlink" title="基础使用"></a>基础使用</h2><ul>
<li><strong>静态路由</strong>：在应用渲染前的初始化阶段配置好路由信息，应用于 RR4 之前的版本。</li>
<li><strong>动态路由</strong>：随着应用渲染而起作用，无需事先配置路由。核心设计理念是一切都是组件，这更符合 React 组件化的思想。</li>
<li><strong>嵌套路由</strong>：Route 渲染的组件内部定义新的 Route，实现页面的局部变换，比如说标题栏不变，内容根据路由引入不同模块。</li>
<li><strong>响应式路由</strong>：手机端访问 &#x2F;admin，竖屏模式下只展示导航栏，横屏时展示导航栏和内容。PC 端根据屏幕大小展示不同内容。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">cnpm i react-router-dom -S</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Route</span>, <span class="title class_">Redirect</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react-router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">BrowserRouter</span> <span class="keyword">as</span> <span class="title class_">Router</span>, <span class="title class_">Route</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react-router-dom&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 动态路由</span></span><br><span class="line">&lt;div id=<span class="string">&quot;app&quot;</span>&gt;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Router</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/&quot;</span> <span class="attr">exact</span> <span class="attr">component</span>=<span class="string">&#123;Home&#125;/</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/detail/:id&quot;</span> <span class="attr">exact</span> <span class="attr">component</span>=<span class="string">&#123;Detail&#125;/</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;/<span class="name">Router</span>&gt;</span></span></span><br><span class="line">&lt;/div&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 嵌套路由</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">About</span> = (<span class="params">&#123; match &#125;</span>) =&gt; (</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&#123;match.url</span> + &#x27;/<span class="attr">other</span>&#x27;&#125; <span class="attr">component</span>=<span class="string">&#123;Other&#125;</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">)</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">App</span> = (<span class="params"></span>) =&gt; (</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Router</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    // 路由重定向</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/&quot;</span> <span class="attr">render</span>=<span class="string">&#123;()</span>=&gt;</span> ( <span class="tag">&lt;<span class="name">Redirect</span> <span class="attr">to</span>=<span class="string">&quot;/home&quot;</span> /&gt;</span>) &#125;&gt;<span class="tag">&lt;/<span class="name">Route</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/home&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Home&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/about&quot;</span> <span class="attr">component</span>=<span class="string">&#123;About&#125;</span> /&gt;</span> </span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;/<span class="name">Router</span>&gt;</span></span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 响应式路由</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">App</span> = (<span class="params"></span>) =&gt; (</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">AppLayout</span>&gt;</span> <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/admin&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Admin&#125;</span> /&gt;</span> <span class="tag">&lt;/<span class="name">AppLayout</span>&gt;</span></span></span><br><span class="line">)</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Admin</span> = (<span class="params"></span>) =&gt; (</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">Layout</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Nav</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">Media</span> <span class="attr">query</span>=<span class="string">&#123;PRETTY_SMALL&#125;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      &#123;screenIsSmall =&gt; screenIsSmall</span></span><br><span class="line"><span class="language-xml">        ? <span class="tag">&lt;<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">&quot;/admin/dashboard&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Dashboard&#125;/</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/admin/other&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Other&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">          <span class="tag">&lt;/<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        : <span class="tag">&lt;<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Route</span> <span class="attr">exact</span> <span class="attr">path</span>=<span class="string">&quot;/admin/dashboard&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Dashboard&#125;/</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Route</span> <span class="attr">path</span>=<span class="string">&quot;/admin/other&quot;</span> <span class="attr">component</span>=<span class="string">&#123;Other&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">Redirect</span> <span class="attr">from</span>=<span class="string">&quot;/admin&quot;</span> <span class="attr">to</span>=<span class="string">&quot;/admin/dashboard&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">          <span class="tag">&lt;/<span class="name">Switch</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      &#125;</span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">Media</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;/<span class="name">Layout</span>&gt;</span></span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>


<h1 id="六、状态管理"><a href="#六、状态管理" class="headerlink" title="六、状态管理"></a>六、状态管理</h1><blockquote>
<p>将组件之间的共享数据抽取出来进行统一管理，通过约定规则更新而实现可预测的状态更新。</p>
</blockquote>
<h2 id="Context"><a href="#Context" class="headerlink" title="Context"></a>Context</h2><blockquote>
<p>实现组件和子孙组件之间跨层级通信，React 原生支持的状态管理方案。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState, createContext, useContext &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">NotesContext</span> = <span class="title function_">createContext</span>();</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">Main</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [notes, setNotes] = <span class="title function_">useState</span>([])</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">createNote</span>(<span class="params">note</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> notesArray = [...notes, note]</span><br><span class="line">        <span class="title function_">setNotes</span>(notesArray)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">NotesContext.Provider</span> <span class="attr">value</span>=<span class="string">&#123;&#123;</span> <span class="attr">notes</span>, <span class="attr">createNote</span> &#125;&#125;&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">App</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">NotesContext.Provider</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123;notes, createNote&#125; = <span class="title function_">useContext</span>(<span class="title class_">NotesContext</span>);</span><br><span class="line">    <span class="keyword">const</span> [input, setInput] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">onCreateNote</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="title function_">createNote</span>(input)</span><br><span class="line">        <span class="title function_">setInput</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>My notes app<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;onCreateNote&#125;</span>&gt;</span>Create Note<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;input&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span>=&gt;</span>setInput(e.target.value)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            &#123; notes.map(note =&gt; <span class="tag">&lt;<span class="name">p</span> <span class="attr">key</span>=<span class="string">&#123;note&#125;</span>&gt;</span>Note: &#123;note&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>) &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="React-Query"><a href="#React-Query" class="headerlink" title="React-Query"></a>React-Query</h2><blockquote>
<p>React 获取、缓存和更新服务器数据的 hooks，为轻交互重数据的业务场景提供了极大便利。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 数据请求</span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 后端返回数据</span></span><br><span class="line">    <span class="keyword">const</span> [zen, setZen] = <span class="title class_">React</span>.<span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    <span class="comment">// 加载状态</span></span><br><span class="line">    <span class="keyword">const</span> [isLoading, setIsLoading] = <span class="title class_">React</span>.<span class="title function_">useState</span>(<span class="literal">false</span>);</span><br><span class="line">    <span class="comment">// 是否申请胜利</span></span><br><span class="line">    <span class="keyword">const</span> [isError, setIsError] = <span class="title class_">React</span>.<span class="title function_">useState</span>(<span class="literal">false</span>);</span><br><span class="line">    <span class="comment">// 后端返回的错误信息</span></span><br><span class="line">    <span class="keyword">const</span> [errorMessage, setErrorMessage] = <span class="title class_">React</span>.<span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">fetchData</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">        <span class="title function_">setIsLoading</span>(<span class="literal">true</span>);</span><br><span class="line">        <span class="title function_">fetch</span>(<span class="string">&#x27;https://api.github.com/zen&#x27;</span>)</span><br><span class="line">        .<span class="title function_">then</span>(<span class="keyword">async</span> (res) =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span> (res.<span class="property">status</span> !== <span class="number">200</span>) &#123;</span><br><span class="line">                <span class="keyword">const</span> &#123; message &#125; = <span class="keyword">await</span> res.<span class="title function_">json</span>();</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(message);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> res.<span class="title function_">text</span>();</span><br><span class="line">        &#125;)</span><br><span class="line">        .<span class="title function_">then</span>(<span class="function">(<span class="params">text: string</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">setIsLoading</span>(<span class="literal">false</span>);</span><br><span class="line">            <span class="title function_">setIsError</span>(<span class="literal">false</span>);</span><br><span class="line">            <span class="title function_">setZen</span>(text);</span><br><span class="line">        &#125;)</span><br><span class="line">        .<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">setIsLoading</span>(<span class="literal">false</span>);</span><br><span class="line">            <span class="title function_">setIsError</span>(<span class="literal">true</span>);</span><br><span class="line">            <span class="title function_">setErrorMessage</span>(error.<span class="property">message</span>);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="title class_">React</span>.<span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">fetchData</span>();   <span class="comment">// 初始化申请数据</span></span><br><span class="line">    &#125;, []);</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Zen from Github<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;isLoading ? &#x27;加载中&#x27; : isError ? errorMessage : zen&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            &#123;!isLoading &amp;&amp; (<span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;fetchData&#125;</span>&gt;</span>&#123;isError ? &#x27;重试&#x27; </span></span><br><span class="line"><span class="language-xml">            : &#x27;刷新&#x27;&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span>)&#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// react-query：简单接口</span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; useQuery &#125; <span class="keyword">from</span> <span class="string">&#x27;react-query&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">fetchData</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="string">&#x27;https://api.github.com/zen&#x27;</span>).<span class="title function_">then</span>(<span class="keyword">async</span> (res) =&gt; &#123;</span><br><span class="line">        <span class="keyword">if</span> (res.<span class="property">status</span> !== <span class="number">200</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> &#123; message &#125; = <span class="keyword">await</span> res.<span class="title function_">json</span>();</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(message);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res.<span class="title function_">text</span>();</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@method</span> <span class="variable">useQuery</span></span></span><br><span class="line"><span class="comment">     * <span class="doctag">@prame</span>  queryKeys：查询的唯一标识，string/array/object (数组可加依赖项)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@prame</span>  queryFunc：异步查问函数，组件实例化第一次执行和依赖项更新时重新执行</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@prame</span>  options：内置功能的配置项，比如错误重试、缓存过期、网络恢复时查询等</span></span><br><span class="line"><span class="comment">    **/</span></span><br><span class="line">    <span class="keyword">const</span> zenQuery = <span class="title function_">useQuery</span>([<span class="string">&#x27;zen&#x27;</span>], fetchData);</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Zen from Github<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                &#123;zenQuery.isLoading || zenQuery.isFetching</span></span><br><span class="line"><span class="language-xml">                  ? &#x27;加载中...&#x27;</span></span><br><span class="line"><span class="language-xml">                  : zenQuery.isError</span></span><br><span class="line"><span class="language-xml">                  ? zenQuery.error?.message</span></span><br><span class="line"><span class="language-xml">                  : data&#125;</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            &#123;!zenQuery.isLoading &amp;&amp; !zenQuery.isFetching &amp;&amp; (</span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> &#123; zenQuery.refetch() &#125;&#125;&gt;</span></span><br><span class="line"><span class="language-xml">                  &#123;zenQuery.isError ? &#x27;重试&#x27; : &#x27;刷新&#x27;&#125;</span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            )&#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// react-query：复杂接口</span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; useQuery &#125; <span class="keyword">from</span> <span class="string">&#x27;react-query&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">fetchData</span> = (<span class="params">&#123; queryKey &#125;</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> [, owner, repo] = queryKey;</span><br><span class="line">    <span class="comment">// queryKey 指查询依赖项，每次修改时就会触发接口重新请求</span></span><br><span class="line">    <span class="comment">// https://api.github.com/repos/facebook/react/issues</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="string">`https://api.github.com/repos/<span class="subst">$&#123;owner&#125;</span>/<span class="subst">$&#123;repo&#125;</span>/issues`</span>, &#123;</span><br><span class="line">        <span class="attr">headers</span>: &#123; <span class="title class_">Authorization</span>: <span class="string">&#x27;&#x27;</span> &#125;</span><br><span class="line">    &#125;).<span class="title function_">then</span>(<span class="keyword">async</span> (res) =&gt; &#123;</span><br><span class="line">        <span class="keyword">if</span> (res.<span class="property">status</span> !== <span class="number">200</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> &#123; message &#125; = <span class="keyword">await</span> res.<span class="title function_">json</span>();</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(message);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> res.<span class="title function_">json</span>();</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [inputOwner, setInputOwner] = <span class="title class_">React</span>.<span class="title function_">useState</span>(<span class="string">&#x27;facebook&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> [inputRepo, setInputRepo] = <span class="title class_">React</span>.<span class="title function_">useState</span>(<span class="string">&#x27;react&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> [queryKey, setQueryKey]= <span class="title class_">React</span>.<span class="title function_">useState</span>([inputOwner, inputRepo])</span><br><span class="line">    <span class="keyword">const</span> issueQuery = <span class="title function_">useQuery</span>([<span class="string">&#x27;issues&#x27;</span>, ...queryKey], fetchData);</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">span</span>&gt;</span>仓库：<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">name</span>=<span class="string">&#123;</span>&#x27;<span class="attr">owner</span>&#x27;&#125; </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">value</span>=<span class="string">&#123;inputOwner&#125;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">onChange</span>=<span class="string">&#123;(e)</span> =&gt;</span> setInputOwner(e.target.value)&#125;</span></span><br><span class="line"><span class="language-xml">            /&gt;</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">name</span>=<span class="string">&#123;</span>&#x27;<span class="attr">repo</span>&#x27;&#125; </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">value</span>=<span class="string">&#123;inputRepo&#125;</span> </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">onChange</span>=<span class="string">&#123;(e)</span> =&gt;</span> setInputRepo(e.target.value)&#125; </span></span><br><span class="line"><span class="language-xml">            /&gt;</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">                <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>&#123; setQueryKey([inputOwner, inputRepo]) &#125;&#125;&gt;</span></span><br><span class="line"><span class="language-xml">                查看最新issue信息</span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">h1</span>&gt;</span>仓库&#123;queryKey[0]&#125;/&#123;queryKey[1]&#125;最新issue信息<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                    &#123;issueQuery.isLoading</span></span><br><span class="line"><span class="language-xml">                      ? &#x27;加载中...&#x27;</span></span><br><span class="line"><span class="language-xml">                      : issueQuery.isError</span></span><br><span class="line"><span class="language-xml">                      ? issueQuery.message</span></span><br><span class="line"><span class="language-xml">                      : JSON.stringify(issueQuery.data[0])&#125;</span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Redux"><a href="#Redux" class="headerlink" title="Redux"></a>Redux</h2><blockquote>
<p>基于 Flux 架构单向数据流思想和函数式编程模式而构建状态容器，主要特点为：<code>store 单一数据源</code> (状态存储在唯一的树状对象)、<code>state 只读</code> (纯函数返回新值并不会改变旧值)、<code>reducer 纯函数同步更新</code> (纯函数：输入输出相同类型，不改参数，不依赖外部变量和方法)。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 核心概念</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> store：存储状态和更新规则的唯一树状结构对象</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> action：描述用户行为的对象，type 属性表示执行的操作</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> reducer：同步更新状态的纯函数</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">import</span> &#123; createStore, combineReducers, applyMiddleware &#125; <span class="keyword">from</span> <span class="string">&quot;redux&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> createSageMiddleware <span class="keyword">from</span> <span class="string">&#x27;redux-saga&#x27;</span></span><br><span class="line"><span class="keyword">import</span> mySaga <span class="keyword">from</span> <span class="string">&quot;./views/sagas/sagas.js&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> thunk <span class="keyword">from</span> <span class="string">&#x27;redux-thunk&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> actions = &#123; </span><br><span class="line">    <span class="attr">INCREASE</span>: &#123; <span class="attr">type</span>: <span class="string">&quot;INCREASE&quot;</span> &#125;,</span><br><span class="line">    <span class="attr">DECREASE</span>: &#123; <span class="attr">type</span>: <span class="string">&quot;DECREASE&quot;</span> &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">countReducer</span> = (<span class="params">state=&#123; count: <span class="number">0</span> &#125;, action</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">switch</span> (action.<span class="property">type</span>) &#123;</span><br><span class="line">        <span class="keyword">case</span> actions.<span class="property">INCREASE</span>.<span class="property">type</span>:</span><br><span class="line">            <span class="keyword">return</span> &#123; <span class="attr">count</span>: state.<span class="property">count</span> + <span class="number">1</span> &#125;;</span><br><span class="line">        <span class="keyword">case</span> actions.<span class="property">DECREASE</span>.<span class="property">type</span>:</span><br><span class="line">            <span class="keyword">return</span> &#123; <span class="attr">count</span>: state.<span class="property">count</span> - <span class="number">1</span> &#125;;</span><br><span class="line">        <span class="attr">default</span>:</span><br><span class="line">            <span class="keyword">return</span> state;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">tabReducer</span> = (<span class="params">state=&#123; show: <span class="literal">false</span> &#125;, action</span>)=&gt;&#123;</span><br><span class="line">    <span class="keyword">const</span> newState = &#123;...pre&#125;   </span><br><span class="line">    <span class="keyword">switch</span>(action.<span class="property">type</span>)&#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">&#x27;yes&#x27;</span>:</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">show</span>: <span class="literal">true</span> &#125;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&#x27;yes&#x27;</span>:</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">show</span>: <span class="literal">false</span> &#125;  </span><br><span class="line">      <span class="attr">default</span>:</span><br><span class="line">        <span class="keyword">return</span> state      </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> reducer = <span class="title function_">combineReducers</span>(&#123; countReducer, tabReducer &#125;)</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">logger</span> = store =&gt; <span class="function"><span class="params">next</span> =&gt;</span> <span class="function"><span class="params">action</span> =&gt;</span> &#123; <span class="comment">// 函数柯里化</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(action.<span class="property">type</span> + <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(action));</span><br><span class="line">    <span class="title function_">next</span>(action);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> saga = <span class="title function_">createSageMiddleware</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> <span class="variable">API</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> createStore：创建容器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> getState：获取最新状态</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> dispatch：触发同步更新</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> subscribe：监听更新</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line"><span class="keyword">const</span> store = <span class="title function_">createStore</span>(reducer, applyMiddleware[logger, thunk, saga]);</span><br><span class="line"><span class="keyword">const</span> unsubscribe = store.<span class="title function_">subscribe</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(store.<span class="title function_">getState</span>());</span><br><span class="line">&#125;);</span><br><span class="line">store.<span class="title function_">dispatch</span>(actions.<span class="property">INCREASE</span>);</span><br><span class="line"><span class="title function_">unsubscribe</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 中间件：dispatch 方法的封装和升级</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> <span class="variable">redux</span>-thunk：返回函数时会替代 dispatch 实现异步</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@prame</span> <span class="variable">redux</span>-saga：统一管理所有异步操作，可代替 redux-thunk</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">increaseAsync</span> = (<span class="params"></span>) =&gt; <span class="function">(<span class="params">dispatch</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> <span class="title function_">dispatch</span>(actions.<span class="property">INCREASE</span>), <span class="number">2000</span>)</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">getHttpAction</span> = (<span class="params">url, func</span>) =&gt; <span class="function">(<span class="params">dispatch</span>) =&gt;</span> &#123;</span><br><span class="line">    axios.<span class="title function_">get</span>(url).<span class="title function_">then</span>(<span class="keyword">function</span>(<span class="params">res</span>)&#123;</span><br><span class="line">        <span class="keyword">const</span> action = <span class="title function_">func</span>(res.<span class="property">data</span>)</span><br><span class="line">        <span class="title function_">dispatch</span>(action)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">saga.<span class="title function_">run</span>(mySaga);</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="comment">// sagas.js</span></span><br><span class="line"><span class="keyword">import</span> &#123; takeEvery &#125; <span class="keyword">from</span> <span class="string">&quot;redux-saga/effects&quot;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span>*()&#123;</span><br><span class="line">    <span class="keyword">yield</span> <span class="title function_">takeEvery</span>(<span class="string">&quot;increaseAsync&quot;</span>, <span class="keyword">function</span>*() &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;redux-saga&quot;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// react-redux：针对 react 组件语法开发的 redux 简化版本</span></span><br><span class="line"><span class="comment">// index.js：通过 provider 为后代组件 store (此处为全局)</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Provider</span>, useDispatch, useSelector &#125; <span class="keyword">from</span> <span class="string">&#x27;react-redux&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; configureStore, createReducer, combineReducers&#125; </span><br><span class="line"><span class="keyword">from</span> <span class="string">&#x27;@reduxjs/toolkit&#x27;</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;  </span><br><span class="line">    <span class="keyword">const</span> [input, setInput] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    <span class="keyword">const</span> notes = <span class="title function_">useSelector</span>(<span class="function"><span class="params">state</span> =&gt;</span> state.<span class="property">notes</span>)</span><br><span class="line">    <span class="keyword">const</span> dispatch = <span class="title function_">useDispatch</span>()</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">onCreateNote</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="title function_">dispatch</span>(&#123; <span class="attr">type</span>: <span class="string">&#x27;CREATE_NOTE&#x27;</span>, <span class="attr">note</span>: input &#125;)</span><br><span class="line">        <span class="title function_">setInput</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">h1</span>&gt;</span>My notes app<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;onCreateNote&#125;</span>&gt;</span>Create Note<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;input&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span>=&gt;</span>setInput(e.target.value)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            &#123; notes.map(note =&gt; <span class="tag">&lt;<span class="name">p</span> <span class="attr">key</span>=<span class="string">&#123;note&#125;</span>&gt;</span>Note: &#123;note&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>) &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> notesReducer = <span class="title function_">createReducer</span>([], &#123;</span><br><span class="line">    <span class="string">&#x27;CREATE_NOTE&#x27;</span>: <span class="function">(<span class="params">state, action</span>) =&gt;</span> [...state, action.<span class="property">note</span>]</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">const</span> reducers = <span class="title function_">combineReducers</span>(&#123; <span class="attr">notes</span>: notesReducer &#125;)</span><br><span class="line"><span class="keyword">const</span> store = <span class="title function_">configureStore</span>(&#123; <span class="attr">reducer</span>: reducers &#125;)</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Main</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">Provider</span> <span class="attr">store</span>=<span class="string">&#123;store&#125;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">App</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">Provider</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">Main</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// ReduxPage.js：通过 connect 对象为组件提供状态和更新方法</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&quot;react&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; connect &#125; <span class="keyword">from</span> <span class="string">&quot;react-redux&quot;</span>;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ReduxPage</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> &#123; num, add, minus &#125; = <span class="variable language_">this</span>.<span class="property">props</span>;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">h1</span>&gt;</span>ReduxPage<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">p</span>&gt;</span>&#123;num&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;add&#125;</span>&gt;</span>add<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;minus&#125;</span>&gt;</span>minus<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">        ); </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">mapStateToProps</span> = state =&gt; &#123;  <span class="comment">// 状态映射</span></span><br><span class="line">    <span class="keyword">return</span> &#123; <span class="attr">num</span>: state &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> mapDispatchToProps = &#123;     <span class="comment">// 派发事件映射</span></span><br><span class="line">    <span class="attr">add</span>: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">type</span>: <span class="string">&quot;add&quot;</span> &#125;;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">minus</span>: <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="attr">type</span>: <span class="string">&quot;minus&quot;</span> &#125;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">connect</span>(mapStateToProps, mapDispatchToProps)(<span class="title class_">ReduxPage</span>);</span><br></pre></td></tr></table></figure>


<h2 id="MobX"><a href="#MobX" class="headerlink" title="MobX"></a>MobX</h2><blockquote>
<p>基于 Flux 单向数据流思想填补了 Redux 对概念约束太强而失去灵活性的空缺，适合中小型项目。主要特点有 <code>state 可变</code>(直接操作而没有回退能力)、<code>多个数据源</code>(划分多个模块而不利于维护)、<code>面向对象编程</code>(将状态包装成可观察对象)、<code>响应式编程</code>(声明变化的联动关系)。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// npm install mobx mobx-react-lite</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; observer &#125; <span class="keyword">from</span> <span class="string">&quot;mobx-react-lite&quot;</span></span><br><span class="line"><span class="keyword">import</span> &#123; makeAutoObservable &#125; <span class="keyword">from</span> <span class="string">&#x27;mobx&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">NoteStore</span> &#123;</span><br><span class="line">    notes = []</span><br><span class="line">    <span class="title function_">createNote</span>(<span class="params">note</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">notes</span> = [...<span class="variable language_">this</span>.<span class="property">notes</span>, note]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="title function_">makeAutoObservable</span>(<span class="variable language_">this</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Notes</span> = <span class="keyword">new</span> <span class="title class_">NoteStore</span>()</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span> = <span class="title function_">observer</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> [input, setInput] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    <span class="keyword">const</span> &#123; notes &#125; = <span class="title class_">Notes</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">onCreateNote</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="title class_">Notes</span>.<span class="title function_">createNote</span>(input)</span><br><span class="line">        <span class="title function_">setInput</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;onCreateNote&#125;</span>&gt;</span>Create Note<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;input&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span>=&gt;</span>setInput(e.target.value)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            &#123; notes.map(note =&gt; <span class="tag">&lt;<span class="name">p</span> <span class="attr">key</span>=<span class="string">&#123;note&#125;</span>&gt;</span>Note: &#123;note&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>) &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span></span><br></pre></td></tr></table></figure>

<h2 id="XState"><a href="#XState" class="headerlink" title="XState"></a>XState</h2><blockquote>
<p>试图解决现代页面复杂性的问题，并且依赖于有限状态机的思想和实现。</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// npm install xstate @xstate/react</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; useService &#125; <span class="keyword">from</span> <span class="string">&#x27;@xstate/react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Machine</span>, assign, interpret &#125; <span class="keyword">from</span> <span class="string">&#x27;xstate&#x27;</span></span><br><span class="line"><span class="keyword">const</span> notesMachine = <span class="title class_">Machine</span>(&#123;</span><br><span class="line">    <span class="attr">id</span>: <span class="string">&#x27;notes&#x27;</span>,</span><br><span class="line">    <span class="attr">initial</span>: <span class="string">&#x27;ready&#x27;</span>,</span><br><span class="line">    <span class="attr">context</span>: &#123; <span class="attr">notes</span>: [], <span class="attr">note</span>: <span class="string">&#x27;&#x27;</span> &#125;,</span><br><span class="line">    <span class="attr">states</span>: &#123; <span class="attr">ready</span>: &#123;&#125; &#125;,</span><br><span class="line">    <span class="attr">on</span>: &#123;</span><br><span class="line">        <span class="string">&quot;CHANGE&quot;</span>: &#123;</span><br><span class="line">            <span class="attr">actions</span>: [</span><br><span class="line">                <span class="title function_">assign</span>(&#123; <span class="attr">note</span>: <span class="function">(<span class="params">_, event</span>) =&gt;</span> event.<span class="property">value</span> &#125;)</span><br><span class="line">            ]</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&quot;CREATE&quot;</span>: &#123;</span><br><span class="line">            <span class="attr">actions</span>: [</span><br><span class="line">                <span class="title function_">assign</span>(&#123;</span><br><span class="line">                    <span class="attr">note</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">                    <span class="attr">notes</span>: <span class="function"><span class="params">context</span> =&gt;</span> [...context.<span class="property">notes</span>, context.<span class="property">note</span>]</span><br><span class="line">                &#125;)</span><br><span class="line">            ]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">const</span> service = <span class="title function_">interpret</span>(notesMachine).<span class="title function_">start</span>()</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [state, send] = <span class="title function_">useService</span>(service)</span><br><span class="line">    <span class="keyword">const</span> &#123; <span class="attr">context</span>: &#123; note, notes&#125; &#125; = state</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span>=&gt;</span>send(&#123;type: &#x27;CREATE&#x27;&#125;)&#125;&gt;Create<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;note&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span> =&gt;</span> send(&#123; type: &#x27;CHANGE&#x27;, </span></span><br><span class="line"><span class="language-xml">            value: e.target.value&#125;)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            &#123; notes.map(note =&gt; <span class="tag">&lt;<span class="name">p</span> <span class="attr">key</span>=<span class="string">&#123;note&#125;</span>&gt;</span>Note: &#123;note&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>) &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Recoil"><a href="#Recoil" class="headerlink" title="Recoil"></a>Recoil</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// npm install recoil</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">RecoilRoot</span>, atom, useRecoilState &#125; <span class="keyword">from</span> <span class="string">&#x27;recoil&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> notesState = <span class="title function_">atom</span>(&#123;</span><br><span class="line">    <span class="attr">key</span>: <span class="string">&#x27;notesState&#x27;</span>,</span><br><span class="line">    <span class="attr">default</span>: []</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">Main</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">RecoilRoot</span>&gt;</span> <span class="tag">&lt;<span class="name">App</span> /&gt;</span> <span class="tag">&lt;/<span class="name">RecoilRoot</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">App</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [notes, setNotes] = <span class="title function_">useRecoilState</span>(notesState);</span><br><span class="line">    <span class="keyword">const</span> [input, setInput] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">createNote</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> notesArray = [...notes, input]</span><br><span class="line">        <span class="title function_">setNotes</span>(notesArray)</span><br><span class="line">        <span class="title function_">setInput</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;createNote&#125;</span>&gt;</span>Create Note<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&#123;input&#125;</span> <span class="attr">onChange</span>=<span class="string">&#123;e</span>=&gt;</span>setInput(e.target.value)&#125; /&gt;</span></span><br><span class="line"><span class="language-xml">            &#123; notes.map(note =&gt; <span class="tag">&lt;<span class="name">p</span> <span class="attr">key</span>=<span class="string">&#123;note&#125;</span>&gt;</span>Note: &#123;note&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span>) &#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="Dva"><a href="#Dva" class="headerlink" title="Dva"></a>Dva</h2><blockquote>
<p>一个为了简化开发基于 redux、redux-saga 实现的数据流方案，可以看作是一个轻量级的应用框架：<code>dva = react-router + redux + redux-saga</code>。model 对象上定义了所有的应用逻辑并通过 namespace 区分，通过 state 存储数据，通过 subsciprtions 实现监听，通过 effect 发起异步操作，通过 reducer 执行同步操作，</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line">npm install dva-cli -g</span><br><span class="line">dva <span class="keyword">new</span> dva-quickstart</span><br><span class="line">cd dva-quickstart</span><br><span class="line">npm start</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// index.js</span></span><br><span class="line"><span class="keyword">import</span> dva <span class="keyword">from</span> <span class="string">&#x27;dva&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;./index.css&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> app = <span class="title function_">dva</span>();    <span class="comment">// Initialize</span></span><br><span class="line"><span class="comment">// app.use(&#123;&#125;);       // Plugins</span></span><br><span class="line"><span class="comment">// app.model(require(&#x27;./models/example&#x27;).default);  // Model</span></span><br><span class="line">app.<span class="title function_">router</span>(<span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>).<span class="property">default</span>);   <span class="comment">// Router</span></span><br><span class="line">app.<span class="title function_">start</span>(<span class="string">&#x27;#root&#x27;</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 页面连接 redux</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span> <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; connect &#125; <span class="keyword">from</span> <span class="string">&#x27;dva&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> styles <span class="keyword">from</span> <span class="string">&#x27;./IndexPage.css&#x27;</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">IndexPage</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> (<span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&#123;styles.normal&#125;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">IndexPage</span>.<span class="property">propTypes</span> = &#123; &#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">connect</span>()(<span class="title class_">IndexPage</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// app.model 对象定义了所有的应用逻辑</span></span><br><span class="line"><span class="keyword">import</span> &#123;routerRedux&#125; <span class="keyword">from</span> <span class="string">&#x27;dva/router&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="attr">namespace</span>: <span class="string">&#x27;example&#x27;</span>,</span><br><span class="line">    <span class="attr">state</span>: &#123;&#125;,</span><br><span class="line">    <span class="attr">subscriptions</span>: &#123;</span><br><span class="line">        <span class="title function_">setup</span>(<span class="params">&#123; dispatch, history &#125;</span>) &#123; &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">effects</span>: &#123;</span><br><span class="line">        *<span class="title function_">fetch</span>(<span class="params">&#123; payload &#125;, &#123; call, put &#125;</span>) &#123;</span><br><span class="line">            <span class="keyword">yield</span> <span class="title function_">put</span>(&#123; <span class="attr">type</span>: <span class="string">&#x27;save&#x27;</span> &#125;);</span><br><span class="line">            <span class="keyword">yield</span>.<span class="title function_">put</span>(routerRedux.<span class="title function_">push</span>(<span class="string">&#x27;/&#x27;</span>))</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">reducers</span>: &#123;</span><br><span class="line">        <span class="title function_">save</span>(<span class="params">state, action</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> &#123; ...state, ...action.<span class="property">payload</span> &#125;;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>





    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2019/08/17/10-1-React%E6%A1%86%E6%9E%B6/" title="React 框架">https://chuangges.gitee.io/2019/08/17/10-1-React框架/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/08/03/9-2-%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91/" rel="prev" title="微信小程序项目开发">
      <i class="fa fa-chevron-left"></i> 微信小程序项目开发
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/08/29/10-2-React%E5%B7%A5%E5%85%B7%E5%BA%93/" rel="next" title="React 工具库">
      React 工具库 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E5%BC%80%E5%8F%91%E6%8A%80%E6%9C%AF"><span class="nav-number">1.</span> <span class="nav-text">一、开发技术</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#React-%E7%AE%80%E4%BB%8B"><span class="nav-number">1.1.</span> <span class="nav-text">React 简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA"><span class="nav-number">1.2.</span> <span class="nav-text">项目构建</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%B7%E5%BC%8F%E7%AD%96%E7%95%A5"><span class="nav-number">1.3.</span> <span class="nav-text">样式策略</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JSX-%E8%AF%AD%E6%B3%95"><span class="nav-number">1.4.</span> <span class="nav-text">JSX 语法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Vite-%E5%B7%A5%E5%85%B7"><span class="nav-number">1.5.</span> <span class="nav-text">Vite 工具</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E7%BB%84%E4%BB%B6%E5%BC%80%E5%8F%91"><span class="nav-number">2.</span> <span class="nav-text">三、组件开发</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E5%88%9B%E5%BB%BA"><span class="nav-number">2.1.</span> <span class="nav-text">组件创建</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8B%E4%BB%B6%E7%BB%91%E5%AE%9A"><span class="nav-number">2.2.</span> <span class="nav-text">事件绑定</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">2.3.</span> <span class="nav-text">生命周期</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6-API"><span class="nav-number">2.4.</span> <span class="nav-text">组件 API</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Ref-%E7%94%A8%E6%B3%95"><span class="nav-number">2.5.</span> <span class="nav-text">Ref 用法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6%E9%80%9A%E4%BF%A1"><span class="nav-number">2.6.</span> <span class="nav-text">组件通信</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94%E3%80%81%E8%B7%AF%E7%94%B1%E5%8A%9F%E8%83%BD"><span class="nav-number">3.</span> <span class="nav-text">五、路由功能</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%AF%E7%94%B1%E7%BB%84%E4%BB%B6"><span class="nav-number">3.1.</span> <span class="nav-text">路由组件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1"><span class="nav-number">3.2.</span> <span class="nav-text">路由对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82"><span class="nav-number">3.3.</span> <span class="nav-text">路由传参</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8"><span class="nav-number">3.4.</span> <span class="nav-text">基础使用</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%AD%E3%80%81%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86"><span class="nav-number">4.</span> <span class="nav-text">六、状态管理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Context"><span class="nav-number">4.1.</span> <span class="nav-text">Context</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#React-Query"><span class="nav-number">4.2.</span> <span class="nav-text">React-Query</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Redux"><span class="nav-number">4.3.</span> <span class="nav-text">Redux</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#MobX"><span class="nav-number">4.4.</span> <span class="nav-text">MobX</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#XState"><span class="nav-number">4.5.</span> <span class="nav-text">XState</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Recoil"><span class="nav-number">4.6.</span> <span class="nav-text">Recoil</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Dva"><span class="nav-number">4.7.</span> <span class="nav-text">Dva</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
